React Hooks Exhaustive-deps 异步无限循环
React Hooks Exhaustive-deps async infinite Loop
我有以下组件:
import React, { useState, useEffect } from "react";
const App = () => {
const [data, setData] = useState<null | any[]>(null);
const [checked, setChecked] = useState(false);
const [loading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
(async () => {
if (data) {
// Could do something else here if data already exsisted
console.log("Data exists already");
}
const ret = await fetch("https://jsonplaceholder.typicode.com/users?delay=1000", { cache: "no-store" });
const json = await ret.json();
setData(json);
setLoading(false);
})();
}, [checked]);
return (
<>
<h1>useEffect Testing {loading && " ⌛"}</h1>
<hr />
<input type="checkbox" checked={checked} onChange={(e) => setChecked(e.target.checked)} />
<pre style={{ fontSize: "0.8em" }}>{JSON.stringify(data)}</pre>
</>
);
};
export default App;
目前,我的 if(data)
毫无意义,但是如果我想检查当前的 data
状态,然后 运行 基于状态的异步函数 eslint(react-hooks/exhaustive-deps) 告诉我钩子缺少 data
依赖项,确实如此。当我将数据添加到导致无限循环的依赖列表时,问题就来了。
知道如何解决这个问题吗?感觉它应该是相当简单的模式,但是我发现的所有内容都建议使用扩展的 setState(prev => prev + 1)
重载,这在这种情况下对我没有帮助。
您正在设置 data
并且还在效果中读取它。这将导致无限循环,除非您手动停止它。这里有一些解决方案。
Return如果有数据而不是修改它:
useEffect(() => {
setLoading(true);
(async () => {
if (data) {
// Could do something else here if data already exsisted
console.log("Data exists already");
return;
}
const ret = await fetch("https://jsonplaceholder.typicode.com/users?delay=1000", { cache: "no-store" });
const json = await ret.json();
setData(json);
setLoading(false);
})();
}, [checked, data]);
消除你对 data
设置效果的依赖(我会做的):
useEffect(() => {
setLoading(true);
(async () => {
const ret = await fetch("https://jsonplaceholder.typicode.com/users?delay=1000", { cache: "no-store" });
const json = await ret.json();
setData(json);
setLoading(false);
})();
}, [checked]);
useEffect(() => {
if (data) {
// Could do something else here if data already exsisted
console.log("Data changed and exists!");
}
}, [data]);
或者您可以手动执行一些操作来停止无限循环。
useEffect(() => {
if (loading || data) {
console.log('Do something with loading or data, but do not modify it!')
return;
}
setLoading(true);
(async () => {
const ret = await fetch("https://jsonplaceholder.typicode.com/users?delay=1000", { cache: "no-store" });
const json = await ret.json();
setData(json);
setLoading(false);
})();
}, [checked, data]);
我有以下组件:
import React, { useState, useEffect } from "react";
const App = () => {
const [data, setData] = useState<null | any[]>(null);
const [checked, setChecked] = useState(false);
const [loading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
(async () => {
if (data) {
// Could do something else here if data already exsisted
console.log("Data exists already");
}
const ret = await fetch("https://jsonplaceholder.typicode.com/users?delay=1000", { cache: "no-store" });
const json = await ret.json();
setData(json);
setLoading(false);
})();
}, [checked]);
return (
<>
<h1>useEffect Testing {loading && " ⌛"}</h1>
<hr />
<input type="checkbox" checked={checked} onChange={(e) => setChecked(e.target.checked)} />
<pre style={{ fontSize: "0.8em" }}>{JSON.stringify(data)}</pre>
</>
);
};
export default App;
目前,我的 if(data)
毫无意义,但是如果我想检查当前的 data
状态,然后 运行 基于状态的异步函数 eslint(react-hooks/exhaustive-deps) 告诉我钩子缺少 data
依赖项,确实如此。当我将数据添加到导致无限循环的依赖列表时,问题就来了。
知道如何解决这个问题吗?感觉它应该是相当简单的模式,但是我发现的所有内容都建议使用扩展的 setState(prev => prev + 1)
重载,这在这种情况下对我没有帮助。
您正在设置 data
并且还在效果中读取它。这将导致无限循环,除非您手动停止它。这里有一些解决方案。
Return如果有数据而不是修改它:
useEffect(() => {
setLoading(true);
(async () => {
if (data) {
// Could do something else here if data already exsisted
console.log("Data exists already");
return;
}
const ret = await fetch("https://jsonplaceholder.typicode.com/users?delay=1000", { cache: "no-store" });
const json = await ret.json();
setData(json);
setLoading(false);
})();
}, [checked, data]);
消除你对 data
设置效果的依赖(我会做的):
useEffect(() => {
setLoading(true);
(async () => {
const ret = await fetch("https://jsonplaceholder.typicode.com/users?delay=1000", { cache: "no-store" });
const json = await ret.json();
setData(json);
setLoading(false);
})();
}, [checked]);
useEffect(() => {
if (data) {
// Could do something else here if data already exsisted
console.log("Data changed and exists!");
}
}, [data]);
或者您可以手动执行一些操作来停止无限循环。
useEffect(() => {
if (loading || data) {
console.log('Do something with loading or data, but do not modify it!')
return;
}
setLoading(true);
(async () => {
const ret = await fetch("https://jsonplaceholder.typicode.com/users?delay=1000", { cache: "no-store" });
const json = await ret.json();
setData(json);
setLoading(false);
})();
}, [checked, data]);