下面的代码在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
将被重新呈现一次,并使用新字符串,因此它将被打印一次。奇怪的是,为什么它打印了两次,而当开发控制台打开时,它只打印了一次?
据我所知,我们看到的对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钩子时,我的应用程序只会呈现一次我认为应该呈现的效果。任何关于为什么会发生这种情况的指导都是受欢迎的