我有一个自定义钩子,用于在我的react前端应用程序上发出API请求,但是该钩子似乎有一个错误。
它按预期发出API请求,但是每当我卸载正在其中发出请求的当前容器/页面时,我的钩子都不知道该页面已被卸载,因此它不会取消请求,因此会做出反应“无法在未安装的组件上执行React状态更新”警告。
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 }];
}
答案 0 :(得分:0)
现在,您在错误的位置检查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
。
答案 1 :(得分:0)
我使用以下钩子来获取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