如何在React应用程序中使用async/await中止Axios请求?



嗨,我创建了一个React钩子来处理Axios请求。我遇到的问题是,我无法成功地中止请求以防止内存泄漏。当我在两个使用钩子的页面之间切换时,我得到错误:

无法在未挂载的组件上执行React状态更新。这是无操作,但它表明应用程序中存在内存泄漏。修复,在useEffect清理中取消所有订阅和异步任务函数。

useAxios钩子代码:

import { useState, useEffect } from "react";
import axios from "axios";
const useAxios = (url, method = "GET") => {
const [data, setData] = useState([]);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(false);
const [body, setBody] = useState(null);
useEffect(() => {
const controller = new AbortController();
const getData = async (body) => {
setLoading(true);
try {
const res = body
? await axios.post(url, body, {
signal: controller.signal,
})
: await axios.get(url, {
signal: controller.signal,
});
setData(res.data);
setError(null);
setLoading(false);
} catch (err) {
console.log(err.message);
setError(err.message);
setLoading(false);
}
};
if (method === "GET") {
getData();
} else if (method === "POST") {
getData(body);
}
return () => {
controller.abort();
};
}, [url, method, body]);
return { data, error, loading, setBody };
};
export default useAxios;

您的setErrorsetLoading在中止时都将触发。

所以你需要在卸载回调中设置一个标志。然后,您可以有条件地基于此调用setError/setLoading

useEffect(() => {
let aborting = false;
try {
....
} catch (err) {
console.log(err.message);
if (!aborting) {
setError(err.message);
setLoading(false);
}
} 
....
return () => {
aborting = true;
controller.abort();
}
}, ...

防止内存泄漏

请注意,这实际上并不是内存泄漏,它只是一个可能来自内存泄漏的警告。如。使用addEventListener而不使用removeEventListener但是在任何一种情况下,您仍然希望在已挂载的组件上防止setState

最新更新