useAxios:用于任何 Axios 调用的 React hook

2025-06-07

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/>}
  );
};
Enter fullscreen mode Exit fullscreen mode

概述

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;
Enter fullscreen mode Exit fullscreen mode

结论

最好取消多余的请求,以免造成内存泄漏!希望这个例子对你有所帮助。

文章来源:https://dev.to/kwhitejr/useaxios-react-hook-for-any-axios-call-12b7
PREV
DevOps 是一种不断发展的文化,而不是一个团队
NEXT
如何:设置可单元测试的 Jenkins 共享管道库