Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs React hook useRender调用了两次,如果随后执行bailing并设置状态_Reactjs_React Hooks_Use State_Use Reducer_React Lifecycle Hooks - Fatal编程技术网

Reactjs React hook useRender调用了两次,如果随后执行bailing并设置状态

Reactjs React hook useRender调用了两次,如果随后执行bailing并设置状态,reactjs,react-hooks,use-state,use-reducer,react-lifecycle-hooks,Reactjs,React Hooks,Use State,Use Reducer,React Lifecycle Hooks,我不确定这是否是预期的行为,但如果在使用useReducer钩子时退出dispatch(),则如果后面跟着一个呈现,则该操作会发生两次。让我解释一下: // bailing out to prevent re-rendering const testReducer = (state, action) => { switch (action.type) { case "ADD": state.test += 1 return state; } };

我不确定这是否是预期的行为,但如果在使用useReducer钩子时退出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>
  );
}
为什么会这样?这是预期的行为还是bug? 沙盒示例:


更新: 在进行一些调试之后,看起来只有在使用React.StrictMode包装时才会发生这种行为

有人知道这是什么原因吗?

根据,react故意用相同的动作调用reducer函数两次,以暴露未被注意到的潜在有害副作用,这正是您的案例所发生的情况

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


你能为此创建一个可复制的示例吗。我创建了一个,但没有发现任何问题。附属的。在看了你的之后,我不明白我在做什么的区别以及为什么我的行为是这样的。哇,真有趣。那么这个例子是不安全的呢?是因为我们在同一个单击事件上更新了useState状态和useReducer状态吗?这是因为您违反了这样的假设,即reducer应该是无副作用的、幂等的,并且在发生更改时总是返回新值。你违反了第三条规则(尽管是故意的)。对我来说,这更像是一个惯例。但是,由于有一整套生态系统和机制(如救助)围绕着这一假设而建立,这就成为了一项要求。所以strictMode决定公开它。
// non-bailing reducer
const testReducer = (state, action) => {
  switch (action.type) {
    case "ADD":
      return {
        test: state.test + 1,
      };
  }
};