React version 18中strict-mode的变化导致我的代码呈现两次,这导致在axios中出现错误中止控制器,但我不知道如何清除错误在应用程序渲染两次后从浏览器控制台。
请注意:我正在一个注册/登录应用程序,甚至在我成功登录后,React将我带回到登录页面,因为axios误差
useEffect(() => {
let isMounted = true;
// used by axios to cancel request
const controller = new AbortController();
const getGoals = async () => {
try {
const response = await goalPrivate.get("/goals", {
// option to cancel request
signal: controller.signal
})
console.log(response?.data);
// set goals state when component mounts
isMounted && setGoals(response?.data);
} catch (error) {
console.log(error.message);
// when refreshToken expires
navigate("/login", { state: { from: location }, replace: true });
}
}
getGoals();
// cleanup function
return () => {
// don't set state if component unmounts
isMounted = false;
// cancel request if component unmounts
controller.abort();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
React StrictMode调用所有Effects两次,以确保它们的清理/卸载处理程序按预期工作。您可能需要相应地更改您的效果,即使它们有一个空的依赖项列表,并且在站点关闭之前通常不会卸载。
注意,这只发生在Strict +开发模式下。在生产版本中,特效只会被调用一次,并且当它们的依赖关系发生变化时。
查看更多内容,请参见https://reactjs.org/docs/strict-mode.html#ensuring-reusable-state
有同样的问题,并以这种方式修复
当abortController被终止时,你跳转到catch,这样你就可以检查信号是否被终止,或者不执行剩下的代码。
useEffect(() => {
const abortController = new AbortController();
fetch("https://pokeapi.co/api/v2/pokemon", {
signal: abortController.signal,
})
.then((res) => res.json())
.then(console.log)
.catch((err) => {
if (abortController.signal.aborted) return;
console.log(err);
// Your navigate
});
return () => {
abortController.abort();
};
}, []);
如果您启用了StrictMode,它将在开发模式下触发两次useEffect,以确保您知道可能出现的副作用。
您应该根据错误码或http状态码对错误响应进行分类。
,
...
try {
// Create axios request
} catch (e: AxiosError) {
if (error.code === 'ERR_CANCELED') {
// When abort controller executed
} else (error.response.status == 401) {
// When you get http code 401 (Un-authenticated)
// Eg:
navigate("/login", { state: { from: location }, replace: true });
} else {
// Etc...
}
}
...
搜索这个问题,我发现解决这个问题的最佳选择是:
- 从你的应用中删除StrictMode(你可以通过从应用组件中删除StricMode标签来做到这一点)
- 使用React Query(无论如何你应该在现代React应用程序中使用)
引用:
https://javascript.plainenglish.io/react - 18 - useeffect -双-电话- api -紧急修复- 724 b7ee6a646
https://blog.bitsrc.io/react-v18-0-useeffect-bug-why-do-effects-run-twice-39babecede93
React 18现在有Strict.Mode
可以挂载,卸载和重新挂载组件,这导致abortController在第一次卸载时发出错误。请记住,这只发生在Strict开发模式下。模式在index.js中应用。我们可以在开发模式下检查这种行为。
try {
// fetch API data
} catch (error) {
if (process.env.NODE_ENV === "development" && error) {
// ignore the error
console.log(error.message);
} else {
// when refreshToken expires, go back to login
navigate("/login", { state: { from: location }, replace: true });
}
}