当前位置: 首页 > 知识库问答 >
问题:

为什么ReactJS组件使用钩子渲染一次或两次取决于开发人员控制台是否打开?

沙岳
2023-03-14

下面的代码在codesandbox的控制台中同时打印两次。io网站(该版本使用stricmode)以及下面的代码段(不使用stricmode):

const { useState, useEffect } = React;

function useCurrentTime() {
  const [timeString, setTimeString] = useState("");

  useEffect(() => {
    const intervalID = setInterval(() => {
      setTimeString(new Date().toLocaleTimeString());
    }, 100);
    return () => clearInterval(intervalID);
  }, []);

  return timeString;
}

function App() {
  const s = useCurrentTime();
  console.log(s);

  return <div className="App">{s}</div>;
}

ReactDOM.render(<App />, document.getElementById("root"));
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.development.js"></script>

演示:https://codesandbox.io/s/gallant-bas-3lq5w?file=/src/App.js(使用StrictMode)

下面是一个使用生产libs的片段;它仍然记录两次:

const { useState, useEffect } = React;

function useCurrentTime() {
  const [timeString, setTimeString] = useState("");

  useEffect(() => {
    const intervalID = setInterval(() => {
      setTimeString(new Date().toLocaleTimeString());
    }, 100);
    return () => clearInterval(intervalID);
  }, []);

  return timeString;
}

function App() {
  const s = useCurrentTime();
  console.log(s);

  return <div className="App">{s}</div>;
}

ReactDOM.render(<App />, document.getElementById("root"));
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>

但是,当我打开开发人员控制台时,我看到每次只打印一次,在codesandbox.io控制台中,我也看到打印一次。

然后,如果我使用create-react-app创建独立的React应用程序,并使用上述代码,每次打印两次。

如何理解这种行为,根据不同情况打印一次或两次?我的想法是,如果状态改变,那么App将被重新呈现一次,并使用新字符串,因此它将被打印一次。奇怪的是,为什么它打印了两次,而当开发控制台打开时,它只打印了一次?

共有1个答案

戚承业
2023-03-14

据我所知,我们看到的对App的双重调用是预期行为。从useState文档中:

退出状态更新

如果您将状态钩子更新为与当前状态相同的值,React将在不呈现子级或射击效果的情况下退出。说明:React使用Object.is比较算法。

请注意,在退出之前,React可能仍然需要再次渲染该特定组件。这不应该是一个问题,因为反应不会不必要地“深入”树。如果您在渲染时进行昂贵的计算,您可以使用useMemo优化它们。

关键点是“注意,React可能仍然需要在退出之前再次渲染特定组件…”而且“…React不会不必要地“深入”树中…”

事实上,如果我更新您的示例,使其使用子组件来显示时间字符串,我们只会看到每个timeString值调用一次子组件,而不是App值的两倍,即使子组件未包装在React中。备忘录

const { useState, useEffect } = React;

function useCurrentTime() {
    const [timeString, setTimeString] = useState("");
  
    useEffect(() => {
        const intervalID = setInterval(() => {
            setTimeString(new Date().toLocaleTimeString());
        }, 100);
        return () => clearInterval(intervalID);
    }, []);
  
    return timeString;
}

function ShowTime({timeString}) {
    console.log("ShowTime", timeString);
    return <div className="App">{timeString}</div>;
}

function App() {
    const s = useCurrentTime();
    console.log("App", s);
  
    return <ShowTime timeString={s} />;
}

ReactDOM.render(<App />, document.getElementById("root"));
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
 类似资料:
  • 非常简单的例子:我的App.js文件读取 我的Test.js文件上写着 在控制台中,渲染总是打印两次。为什么啊?

  • 也许你们中的一些人可以帮我睁开眼睛。 我不明白为什么在这段代码中:https://codesandbox.io/s/use-state-renders-twice-6r1xl组件应用程序在安装并单击按钮时呈现两次(console.log被调用两次) 代码: 结果: 它只是一个功能组件挂钩!

  • 我遇到了这个简单的React函数组件,它渲染四次,而我希望它最初渲染一次,执行useffect更新状态,然后再次渲染。相反,控制台发送4个日志输出,表示它渲染了4次。了解react功能组件的基本生命周期的原因和资源吗? https://codesandbox.io/s/solitary-tree-t120d?file=/src/App.js:149-191

  • 此组件渲染两次并抛出错误。我知道这个错误是因为它们在reduce函数中没有返回语句。但我不明白的是,为什么它会渲染两次? 此外,当我删除代码时,它只呈现一次。据我所知,一个组件只能在四种情况下重新渲染 状态的变化 道具的变化 强制渲染 父母重新渲染。 在我的例子中,父组件没有重新渲染(我通过在父组件中使用console.log检查了它),并且这个组件是无状态的,没有道具被传递给它。有人能解释一下这

  • 我有一个组件,我设置了一个计数,让状态更新时,按钮点击。但是当我检查渲染时间时,每次我点击按钮它都会渲染两次。 https://codesandbox.io/s/brave-forest-yre6y?file=/src/App.js 我想知道: 为什么它是这样工作的

  • 我无法理解为什么我的AppReact组件呈现两次,如下面的gif所示。 我插入了一个控制台。在返回组件之前记录日志,查看组件渲染的次数。 每当我移除useState钩子时,我的应用程序只会呈现一次我认为应该呈现的效果。任何关于为什么会发生这种情况的指导都是受欢迎的