SetTimeout 触发两次

Dan*_*ean 5 javascript settimeout reactjs

这是我的页面的 React 代码:

function ExportViewerPage(): JSX.Element {
  const [hasPrinted, setHasPrinted] = useState(false);

  if (!hasPrinted) {
    setHasPrinted(true);
    console.log("Inside if loop, hasPrinted: ", hasPrinted)
    setTimeout(() => {
      console.log("Executing setTimeout: ", hasPrinted)
    });
  }

  return (<div>Page</div>)
}

export default ExportViewerPage;
Run Code Online (Sandbox Code Playgroud)

最终,代码应该执行函数中的代码setTimeout一次。然而,它实际上执行了两次,如控制台所示:

Inside if loop, hasPrinted:  false
Executing setTimeout:  false
Executing setTimeout:  false
Run Code Online (Sandbox Code Playgroud)

奇怪的是,setTimeout函数之前的控制台日志仅执行一次,因此setTimeout不会被调用两次并且hasPrinted设置正确。Chrome 和 Firefox 上都会发生这种情况。

我确实注意到,如果我reactStrictModenext.config.js文件中关闭,则setTimeout只会触发一次。但我仍然很困惑为什么在打开时setTimeout会触发两次reactStrictMode,但它上面的控制台日志只记录一次。

Dan*_*ean 1

该问题是由于严格模式造成的。根据文档,严格模式在开发过程中会调用某些函数两次,以帮助识别副作用。

奇怪的部分是上面的控制台日志也setTimeout没有触发两次。这可以通过文档中的这段代码来解释:

注意:在 React 17 中,React 自动修改控制台方法(如 console.log()),以在第二次调用生命周期函数时静默日志。但是,在某些可以使用解决方法的情况下,它可能会导致不良行为。

由于我使用的是React 17,控制台日志的第二次调用被react静音,所以这就是我感到困惑的原因。

请注意,React 18 中不再是这种情况:

从 React 18 开始,React 不再抑制任何日志。但是,如果您安装了 React DevTools,第二次调用的日志将稍微变暗。React DevTools 还提供了一个设置(默认关闭)来完全抑制它们。