在组件挂载时,useEffect会被执行两次
环境
-
- OS: Windows 10
-
- Node.js: v16.16.0
- React: 18.2.0
目前的情况
当使用 useEffect 时,在组件挂载时,通过一次 fetch 访问 API 并取回信息,那么…
useEffect(() => {
fetch("https://xxxx.com/xxx")
.then(res => res.json())
.then(data => {
console.log(data)
})
} , []);
为什么日本人那么老套,竟然被fetch了两次!!
(10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
(10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
的解释是为了某种结果、理论、行为、事件、状况等的道理或根源。
这是由React18中的StrictMode的附加功能带来的。
在“严格模式”下运行时,为了清除不安全的副作用,React会故意双重渲染组件。
原始出处:
(Source of quote:)
只有在启用StrictMode的情况下,组件才会被渲染两次。
因此,useEffect会执行两次,并且会返回两个fetch结果。
在下面的GitHub议题中进行了讨论。
避免方案
虽然可能还有其他的,但我只列举了找到的。
选项1: 关闭StrictMode方法
- 手っ取り早いのはこれ。
root.render(
- <React.StrictMode>
<App />
- </React.StrictMode>
);
选项1: 忽略第二次执行的结果
有这样一种方法可以应用于公式中。
如果你的 Effect 捕获到了某个东西,清理函数应该要么终止捕获,要么忽略其结果:
useEffect(() => {
let ignore = false;async function startFetching() {
const json = await fetchTodos(userId);
if (!ignore) {
setTodos(json);
}
}startFetching();
return () => {
ignore = true;
};
}, [userId]);
如果你的 Effect 获取了某个东西,清理函数应该要么终止获取,要么忽略其结果:useEffect(() => {
let ignore = false;async function startFetching() {
const json = await fetchTodos(userId);
if (!ignore) {
setTodos(json);
}
}startFetching();
return () => {
ignore = true;
};
}, [userId]);
以下引述来源:
引述源:
印象
起初我感到困惑,但我很快就找到了问题,并在文档中得到了反映,所以能够立即理清了原因,真是太好了。
不过,还是有点不方便啊…
请参阅参考资料。