SetTimeout 会触发两次。

5

这是我为一个页面编写的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;

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

Inside if loop, hasPrinted:  false
Executing setTimeout:  false
Executing setTimeout:  false

奇怪的是,在setTimeout函数之前立即记录的控制台日志只执行一次,因此setTimeout没有被调用两次,并且hasPrinted被正确设置。这在Chrome和Firefox上都会发生。
我注意到,如果我在next.config.js文件中关闭reactStrictModesetTimeout将只触发一次。但我仍然困惑于为什么在打开reactStrictMode的情况下setTimeout会触发两次,但是它上方的控制台日志只记录一次。

3
我认为这是一个开发人员的事情。一旦部署,它就会消失。 - cmgchess
1个回答

1
问题是由于严格模式引起的。根据文档,严格模式在开发中会调用某些函数两次以帮助识别副作用。
奇怪的部分是上面setTimeout之上的控制台日志没有触发两次。这可以通过文档中的以下代码片段来解释:
引用: 注意: 在React 17中,React自动修改控制台方法(如console.log())以消除第二次调用生命周期函数时的日志。但是,在某些情况下可能会导致不良行为,可以使用解决方法。
由于我正在使用React 17,控制台日志的第二次调用被React静音了,所以我感到困惑。
请注意,这在React 18中已不再适用:
引用: 从React 18开始,React不再抑制任何日志。但是,如果您安装了React DevTools,则第二个调用的日志将略微变暗。 React DevTools还提供了一个设置(默认关闭),可以完全禁止它们。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接