【问题标题】:React hook useRender called twice if bailing and setting state afterwardReact hook userRender 调用了两次
【发布时间】:2020-08-18 08:56:02
【问题描述】:

我不确定这是否是预期的行为,但是如果您在使用 useReducer 挂钩时退出调度 (https://reactjs.org/docs/hooks-reference.html#bailing-out-of-a-dispatch),则该操作会在随后进行渲染时发生两次。让我解释一下:

// bailing out to prevent re-rendering
const testReducer = (state, action) => {
  switch (action.type) {
    case "ADD":
      state.test += 1
      return state;
  }
};

const myComponent = () => {
  let [totalClicks, setClicks] = useState(0);
    const [state, setState] = useReducer(testReducer, {
      test: 0,
    });

  const clickHandler = () => {
    setState({type: 'ADD'});
    setClicks((totalClicks += 1));
  };

  return (
    <div>
      <button onClick={clickHandler}>+</button>
      <p>{totalClicks}</p>
      <p>test count: {state.test}</p>
    </div>
  );
}

当您单击该按钮时,state.test 增加 2,而 totalClicks 增加 1。但是,如果我要更改减速器,使其不会像下面那样保释,它们都会增加 1。

// non-bailing reducer
const testReducer = (state, action) => {
  switch (action.type) {
    case "ADD":
      return {
        test: state.test + 1,
      };
  }
};

这是为什么?这是预期的行为还是错误? 沙盒示例:https://codesandbox.io/s/sad-robinson-dds63?file=/src/App.js


更新: 在进行了一些调试之后,看起来这种行为仅在使用 React.StrictMode

包装时才会发生

有谁知道这是什么原因???

【问题讨论】:

标签: reactjs react-hooks use-state use-reducer react-lifecycle-hooks


【解决方案1】:

根据doc of StrictMode,react 故意以相同的操作调用 reducer 函数两次,以便暴露未被注意的潜在有害副作用,这正是您的情况所发生的情况。

严格模式无法自动为您检测副作用,但可以通过使它们更具确定性来帮助您发现它们。这是通过有意双重调用以下函数来完成的:[…] 传递给 useState、useMemo 或 useReducer 的函数

【讨论】:

  • 哇,这很有趣。那么这个例子是不安全的呢?是不是我们在同一个点击事件上更新了我们的 useState 状态和我们的 useReducer 状态?
  • 这是关于你违反了 reducer 应该是无副作用的,幂等的,并且在发生变化时总是返回新值的假设。你打破了第三条规则(尽管是故意的)。对我来说,这更像是一个约定。但是,由于围绕这一假设建立了一大堆生态系统和机制(如救助计划),因此它成为了一项要求。所以 strictMode 决定公开它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-07
  • 2017-04-30
  • 1970-01-01
  • 2020-07-19
  • 2020-12-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多