如何修复 React 警告:无法对未安装的组件执行 React 状态更新
How to fix React WArning : Can't perform a React state update on an unmounted component
每当执行任何与组件相关的异步任务并且该组件卸载时,React 通常会发出此警告 -
Can't perform a React state update on an unmounted component This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
我在互联网上找到了一些将 isMount 标志(通过将其与 useRef 或 useState 一起使用)用作 true 的解决方案,然后在组件卸载时将其更新为 false。但是,根据 React 网站使用 isMount 的正确解决方案是反模式吗?
https://reactjs.org/blog/2015/12/16/ismounted-antipattern.html
在 React 的未来版本中,您可能不需要修复此问题。由于 React 开发团队将在未来的版本中删除此警告。主要原因是此警告有时可能是误报。
根据 Dan Abramov 的提交
https://github.com/facebook/react/pull/22114
但是在那个版本发布之前解决这个问题的解决方案是什么 -
使用 isMountState anti-pattern - 如果有人在他的代码中检查 isMounted 来解决这个问题,那么那个人执行这个检查已经太晚了,因为这个警告表明了同样的检查由 React 完成,但失败了。
如果这个问题是因为异步调用。那么一种可能的解决方案是在您的代码中使用 AbortController API 。
AbortController API 有助于中止任何已进行的 ajax 调用。很酷的东西。对吗?
可以在此处找到更多详细信息
所以如果它是一个获取 API 可以像这样使用 AbortController API
useEffect(() => {
const abortController = new AbortController()
// creating an AbortController
fetch(url, {
signal: abortController.signal
})
// passing the signal to the query
.then(data => {
setState(data)
// if everything went well, set the state
})
.catch(error => {
if (error.name === 'AbortError') return
// if the query has been aborted, do nothing
throw error
})
return () => {
abortController.abort()
// stop the query by aborting on the AbortController on unmount
}
}, [])
如果你使用的是axios,那么好消息是axios还提供了对AbortController的支持APIs -
const fetchData = async (params) => {
setLoading(true);
try {
const result = await axios.request(params);
// more code here
} catch (curError) {
if (axios.isCancel(curError)) {
return false;
}
// error handling code
}
return null;
};
useEffect(() => {
const cancelToken = axios.CancelToken;
const source = cancelToken.source();
fetchData({
...axiosParams,
cancelToken: source.token
});
return () => {
source.cancel("axios request cancelled");
};
}, []);
每当执行任何与组件相关的异步任务并且该组件卸载时,React 通常会发出此警告 -
Can't perform a React state update on an unmounted component This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
我在互联网上找到了一些将 isMount 标志(通过将其与 useRef 或 useState 一起使用)用作 true 的解决方案,然后在组件卸载时将其更新为 false。但是,根据 React 网站使用 isMount 的正确解决方案是反模式吗?
https://reactjs.org/blog/2015/12/16/ismounted-antipattern.html
在 React 的未来版本中,您可能不需要修复此问题。由于 React 开发团队将在未来的版本中删除此警告。主要原因是此警告有时可能是误报。
根据 Dan Abramov 的提交 https://github.com/facebook/react/pull/22114
但是在那个版本发布之前解决这个问题的解决方案是什么 -
使用 isMountState anti-pattern - 如果有人在他的代码中检查 isMounted 来解决这个问题,那么那个人执行这个检查已经太晚了,因为这个警告表明了同样的检查由 React 完成,但失败了。
如果这个问题是因为异步调用。那么一种可能的解决方案是在您的代码中使用 AbortController API 。 AbortController API 有助于中止任何已进行的 ajax 调用。很酷的东西。对吗?
可以在此处找到更多详细信息
所以如果它是一个获取 API 可以像这样使用 AbortController API
useEffect(() => {
const abortController = new AbortController()
// creating an AbortController
fetch(url, {
signal: abortController.signal
})
// passing the signal to the query
.then(data => {
setState(data)
// if everything went well, set the state
})
.catch(error => {
if (error.name === 'AbortError') return
// if the query has been aborted, do nothing
throw error
})
return () => {
abortController.abort()
// stop the query by aborting on the AbortController on unmount
}
}, [])
如果你使用的是axios,那么好消息是axios还提供了对AbortController的支持APIs -
const fetchData = async (params) => {
setLoading(true);
try {
const result = await axios.request(params);
// more code here
} catch (curError) {
if (axios.isCancel(curError)) {
return false;
}
// error handling code
}
return null;
};
useEffect(() => {
const cancelToken = axios.CancelToken;
const source = cancelToken.source();
fetchData({
...axiosParams,
cancelToken: source.token
});
return () => {
source.cancel("axios request cancelled");
};
}, []);