【问题标题】:setTimeout callback called twice in React functional component?在 React 功能组件中调用了两次 setTimeout 回调?
【发布时间】:2021-04-22 05:48:03
【问题描述】:

考虑以下代码:

import React from "react";

function App() {
  console.log("render");

  setTimeout(() => {
    console.log("time is up");
  }, 2000);

  return <div>nothing to see here</div>;
}

export default App;

预期以下输出:

render
time is up

但 Chrome 控制台中的真实输出是:

注意time is up之前的2,这表明time is up被输出了两次。

我不明白为什么 time is up 会输出两次。谁能解释一下?

【问题讨论】:

  • 什么是timers?这只是对全局 setTimeout 的导入还是其他什么?
  • @jonrsharpe Visual Studio Code 为我做了这些。我删除了它,但观察到相同的行为。
  • 当我在本地运行时,我看到render time is up 两次,无法重现。
  • @stefan.at.wpf 您能否从您的 index.js 中验证您没有在 React.StrictMode 中运行?
  • @PrashantVishwakarma 我在严格模式下运行,在移除严格模式后,time is up 只按预期显示一次。我不明白为什么严格模式会改变这一点。你能解释/发布作为答案吗?

标签: javascript reactjs create-react-app


【解决方案1】:

组件被渲染两次,因为 CRA 默认设置了 React 的 strict mode,除其他外,它试图帮助您检测副作用(强调我的):

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

  • 类组件constructorrendershouldComponentUpdate方法
  • 类组件静态getDerivedStateFromProps方法
  • 函数组件体
  • 状态更新函数(setState 的第一个参数)
  • 函数传递给useStateuseMemouseReducer

到目前为止,这已被以下帖子所涵盖:


但是,您可能会期望 "render" "time is up" 被记录两次。没有发生的原因是React was updated 故意抑制重复日志:

这会通过临时修补全局控制台来禁用 console.log 当我们严格双重渲染时,第二次渲染过程中的对象 DEV模式。

这仅适用于上面提到的函数中直接的console.logs,不包括setTimeout回调,所以第二个console.log("render")被吞掉了,而第二个console.log("time is up")没有。

【讨论】:

    【解决方案2】:

    我认为这里的问题是您没有将 setTimeout 放入 useEffect 中。这意味着当应用程序重新呈现时,另一个超时将开始并导致您发现的问题。试试这样的。

    import React, {useEffect} from "react";
    
    function App() {
      console.log("render");
    
        useEffect(() => {
          const timer = setTimeout(() => {
            console.log('time is up');
          }, 2000);
    
          return () => {
            clearTimeout(timer);
          }
        }, []);
    
      return <div>nothing to see here</div>;
    }
    
    export default App;
    

    【讨论】:

      【解决方案3】:

      React.StrictMode 是一个旨在缓解开发人员发现与 React 生命周期相关的问题的功能

      仅当您在开发模式下运行并使用额外规则(例如多次渲染组件)进行渲染时才会发生这种情况。

      我认为文档很好地解释了这一点。 StrictMode: React

      可以理解,人们第一次注意到它会很烦人!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-12-01
        • 1970-01-01
        • 2021-06-20
        • 1970-01-01
        • 2013-05-21
        • 1970-01-01
        • 2022-10-18
        • 2020-08-12
        相关资源
        最近更新 更多