为啥useSelector里面的选择器会运行两次?

Posted

技术标签:

【中文标题】为啥useSelector里面的选择器会运行两次?【英文标题】:Why does the selector inside useSelector run twice?为什么useSelector里面的选择器会运行两次? 【发布时间】:2021-04-25 21:29:17 【问题描述】:

为什么useSelector里面的选择器会运行两次?

Example

const selector = (state) => 
  console.log("invoke Selector");

  return state;
;

function App() 
  console.log("render App");

  const count = useSelector(selector);
  const dispatch = useDispatch();
  return (
    <div className="App">
      <button onClick=() => dispatch( type: "INCREMENT" )>Increment</button>
      <button onClick=() => dispatch( type: "DECREMENT" )>Decrement</button>
      <p>count</p>
    </div>
  );

这是一个有效的 sn-p,显示每次 Child 挂载时选择器回调运行两次:

const  Provider, useDispatch, useSelector  = ReactRedux;
const  createStore, applyMiddleware, compose  = Redux;

function count(state, action) 
  console.log('reducing action:',action.type)
  switch (action.type) 
    case "INCREMENT":
      return ...state,count:state.count+1;
    case "DECREMENT":
      return ...state,count:state.count-1;
    default:
      return state;
  


const store = createStore(count,count:0);

const selector = (state) => 
  console.log("invoke Selector",state);

  return state.count;
;

function Child() 
  console.log("render Child");

  const count = useSelector(selector);
  const dispatch = useDispatch();
  return (
    <div className="App">
      <button onClick=() => dispatch( type: "INCREMENT" )>Increment</button>
      <button onClick=() => dispatch( type: "DECREMENT" )>Decrement</button>
      <p>count</p>
    </div>
  );

const App = () => 
  const [show,setShow] = React.useState(true);

  return (<div>
    <button onClick=()=>setShow(s=>!s)>toggle child</button>
    show?<Child />:'none'
  </div>)

const rootElement = document.getElementById("root");

ReactDOM.render(
  <Provider store=store>
    <App />
  </Provider>,
  rootElement
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js"></script>
<div id="root"></div>

【问题讨论】:

如果使用得当,这应该不是问题。您是出于好奇而询问,还是您有与此行为相关的实际问题? (XY问题) @idmean 出于好奇。 【参考方案1】:

因为它在渲染阶段和调度操作之后都运行。因此,第一个日志发生在 &lt;App&gt; 呈现时,第二个日志发生在您单击按钮并调度更新存储状态的操作时。

useSelector 还会在组件挂载后第二次重新运行选择器,以检查是否由于在构建组件树时调度了动作而导致任何其他更改。

【讨论】:

不知道为什么第一次加载app,selector也跑了两次。 因为React double-renders components in &lt;StrictMode&gt;. 但毕竟渲染的时候,对控制台有双重显示 我还删除了示例中的 包装器 已更新 - useSelector 在挂载后运行第二次检查。

以上是关于为啥useSelector里面的选择器会运行两次?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 jQuery UI 的日期选择器会与动态 DOM 发生冲突?

为啥打开对话框后我的 jQuery 选择器会失败?

当我第二次设置它的 ItemsSource 时,为啥这个选择器会崩溃?

为啥 useSelector 不包含任何数据?

访问 vba:为啥 form_delete sub 运行两次

为啥 DevkitARM GBA 链接器会检测到多个定义?