useFetch Can't perform a React state update on an unmounted component 警告
Posted
技术标签:
【中文标题】useFetch Can\'t perform a React state update on an unmounted component 警告【英文标题】:useFetch Can't perform a React state update on an unmounted component warninguseFetch Can't perform a React state update on an unmounted component 警告 【发布时间】:2020-01-15 06:29:30 【问题描述】:我有一个自定义钩子,用于在我的 react 前端应用程序上发出 API 请求,但该钩子似乎有错误。
它按预期发出 API 请求,但每当我卸载发出请求的当前容器/页面时,我的钩子不知道该页面已被卸载,因此它不会取消请求并因此反应抛出'Can't perform a React state update on an unmounted component' 警告。
export function useFetch(initialValue, url, options, key)
const [response, setResponse] = useLocalStorage(key, initialValue);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(false);
useEffect(() =>
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
const isMounted = state: true ;
async function fetchData()
setLoading(true);
try
const res = await axios(
url: url,
baseURL: BASE_URL,
cancelToken: source.token,
...options
);
if (res.data.results)
setResponse(res.data.results);
else
setResponse(res.data);
setLoading(false);
catch (error)
setError(error);
setLoading(false);
if (isMounted.state)
fetchData();
return () =>
isMounted.state = false;
source.cancel('Operation canceled by the user.');
;
// eslint-disable-next-line react-hooks/exhaustive-deps
, [url]);
return [response, error, loading ];
【问题讨论】:
【参考方案1】:现在您在错误的位置检查if(isMounter.state)
。这是您初始化后的下一步。
我认为应该是
const isMounted = state: true ;
async function fetchData()
setLoading(true);
try
const res = await axios(
url: url,
baseURL: BASE_URL,
cancelToken: source.token,
...options
);
if(!isMounted.state) return;
.....
fetchData();
顺便说一句,您不必在那里使用对象:isMounted = true
/isMounted = false
将在关闭后正常工作。
实际上,您混合了两种不同的方法:使用标志(isMounted
)和取消请求。你可以只用一个。取消请求应该有效(据我所知),但它会导致您的 catch
块被执行:
catch (error)
setError(error);
setLoading(false);
看,卸载取消请求,但您的代码仍然尝试设置某些状态。也许你最好用axious.isCancel
检查请求是否失败或取消:
catch (error)
if (!axios.isCancel(error))
setError(error);
setLoading(false);
在这种情况下,您可能会摆脱 isMounted
。
【讨论】:
【参考方案2】:我使用下面的钩子来获取ifMounted
函数
const useIfMounted = () =>
const isMounted = useRef(true)
useEffect(
() => () =>
isMounted.current = false
,[]
)
const ifMounted = useCallback(
func =>
if (isMounted.current && func)
func()
,[]
)
return ifMounted
然后在您的代码中将const ifMounted = useIfMounted()
添加到useFetch
并在您设置的函数之前执行ifMounted(() => setLoading(true)
、ifMounted(() => setError(error))
等......
这是我写的关于这个主题的博文:https://aceluby.github.io/blog/react-hooks-cant-set-state-on-an-unmounted-component
【讨论】:
以上是关于useFetch Can't perform a React state update on an unmounted component 警告的主要内容,如果未能解决你的问题,请参考以下文章
从服务器获取数据并将值传递给 React 中的子组件(useEffect、useFetch..)
Can't migrate a table to Room do to an error with the way booleans is saved in Sqlite
如何处理来自 urllib.request.urlopen() 的响应编码,以避免 TypeError: can't use a string pattern on a bytes-like obje
Python 3.8 TypeError: can't concat str to bytes - TypeError: a bytes-like object is required, not 's