React useState setter 内的更新被调用两次

Nic*_*one 10 javascript reactjs react-hooks

我正在尝试更新 useState setter 范围内的内容。这正如我在以下 codepen 示例中所期望的那样:

更新状态变量之外的值

但正如我的应用程序中所实现的那样,insideCallCount每次toggleCell调用都会被调用两次。相关部分见下文:

  const callCount = useRef(0);
  const insideCallCount = useRef(0);
  const toggleCell = (i) => {
    callCount.current += 1;
    setPattern((pattern) => {
      let newPattern = deepCopyPattern(pattern);
      newPattern[i][selectedSound].on = !newPattern[i][selectedSound].on;
      insideCallCount.current += 1;
      return newPattern;
    });
    console.log('callCount: ', callCount.current);
    console.log('insideCallCount: ', insideCallCount.current);
  };
Run Code Online (Sandbox Code Playgroud)

我多次“切换”按钮后,控制台读数如下所示:

callCount:  1
insideCallCount:  0
callCount:  2
insideCallCount:  2
callCount:  3
insideCallCount:  4
callCount:  4
insideCallCount:  6
callCount:  5
insideCallCount:  8
callCount:  6
insideCallCount:  10
Run Code Online (Sandbox Code Playgroud)

我的理解这与它包含在函数定义中这一事实有关。我尝试将整个内容包装在 useCallback 中,并使用值在依赖项数组中进行监视,但这没有帮助。我缺少什么?

law*_*itt 7

通常情况下,当 React 应用程序中出现意外情况时,请确保StrictMode已禁用。<App/>您会发现它默认包含在index.js新的 create-react-app 版本的文件中。我只能通过用它创建一个新项目然后删除它来重现/修复这个问题。

是否要保留它取决于您。当您创建生产版本时,它不会被包含在内,并且可以帮助识别应用程序中的潜在问题。在测试代​​码的过程中,它将双重调用各种生命周期方法(在类组件中)和挂钩(在功能组件中),以突出显示在未来版本的 React中可能发生意外副作用的地方。

因此,文档建议不要在以下任何情况下执行副作用:

  • 类组件构造函数、render 和 shouldComponentUpdate 方法
  • 类组件静态 getDerivedStateFromProps 方法
  • 功能组件体
  • 状态更新函数(setState 的第一个参数)
  • 传递给 useState、useMemo 或 useReducer 的函数

该列表取自StrictMode 的文档