在组件挂载时,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]);

以下引述来源:

引述源:

 

印象

起初我感到困惑,但我很快就找到了问题,并在文档中得到了反映,所以能够立即理清了原因,真是太好了。
不过,还是有点不方便啊…

请参阅参考资料。

 

广告
将在 10 秒后关闭
bannerAds