useAxios:用于任何 Axios 调用的 React hook
useAxios()
是一个简化异步获取和状态管理的 React Hook。源代码和示例
想提出改进建议吗?我洗耳恭听!请提交问题或发起 PR!
用法
import React, { useState } from "react";
import { useAxios } from "./use-axios";
const App = () => {
const [id, setId] = useState("1");
const axiosConfig = { method: "get", timeout: 2500 };
const { isLoading, isError, response } = useAxios(
`https://pokeapi.co/api/v2/pokemon/${id}`,
axiosConfig
);
return (
{response?.data && <div>{data}</div>}
{isLoading && <LoadingIcon/>}
{isError && <ErrorMsg/>}
);
};
概述
useAxios
是我的通用useAsyncFunc React hook的Axios特定实现。
异步操作的一个问题是,当返回值不再需要时。例如,用户离开页面(请求组件已卸载)或用户提供了新的搜索查询(旧搜索查询的响应是多余的)。
您可能会看到如下错误:
警告:无法对已卸载的组件执行 React 状态更新。这是一个无操作,但它表明您的应用程序存在内存泄漏。要修复此问题,请在 useEffect 清理函数中取消所有订阅和异步任务。
在这些情况下,我们需要取消初始请求。浏览器 Web API 提供了AbortController
相应的接口;它是一个控制器对象,允许你中止一个或多个 Web 请求。Axios 的CancelToken类提供了类似的功能。如果你已经在使用 Axios 库,那么 CancelToken 的实现非常简单。你可以在这里了解更多关于每个实现的信息。
使用Axios
/**
*
* @param {string} url - The url to call
* @param {object} [config] - The axios config object; defaults to GET, etc
* @returns {state} - { isLoading, isError, response }
*/
const useAxios = (url, config) => {
// useReducer manages the local complex state of the async func hook's lifecycle.
// See the source code for the full reducer!
// NOTE: it is easy to modify or expand the reducer to fit your needs.
const [state, dispatch] = useReducer(axiosReducer, {
isLoading: false,
isError: false
});
useEffect(() => {
// Declare Axios cancel token
const source = CancelToken.source();
// Define the axios call
const callAxios = async () => {
// Begin with a clean state
dispatch({ type: "AXIOS_INIT" });
try {
// Straightforward axios call,
// With cancel token inserted into config
const response = await axios(url, {
...config,
cancelToken: source.token
});
dispatch({ type: "AXIOS_SUCCESS", payload: response });
} catch (err) {
// Two options on error:
// 1. If error is an axios cancel, simply return and move on
// 2. For all other errors, assume async failure and dispatch failure action
if (isCancel(err)) {
console.log("Canceled request.");
return;
}
dispatch({ type: "AXIOS_FAILURE" });
}
};
// Invoke the defined axios call
callAxios();
// On unmount, cancel the request
return () => {
source.cancel("Operation canceled.");
};
// NOTE: here be dragon!
// My instinct was include the axios config in this array, e.g. [url, config]
// This causes an infinite re-render loop that I have not debugged yet :-/
}, [url]);
return state;
};
export default useAxios;
结论
最好取消多余的请求,以免造成内存泄漏!希望这个例子对你有所帮助。
文章来源:https://dev.to/kwhitejr/useaxios-react-hook-for-any-axios-call-12b7