首页 > 解决方案 > 执行 axios 请求的自定义钩子 [React, Typescript]

问题描述

我正在尝试创建一个可重用的自定义钩子(useRequest),我可以在其中使用 axios 获取数据,显示它并具有加载状态。如果出现错误,我希望它被 useRequest 捕获。我无法捕获最终错误并将 axios 请求传递给 useRequest。目前我只得到空的错误消息。

编辑:我使用生成的 api,它使用 axios。因此,要发出我的 fetch 请求,它看起来像这样:

import {GeneratedApi} from '/generatedApi'

const generatedApi = new GeneratedApi(configuration) //configuration is for editing the headers etc.
const response = await generatedApi.getData();
setData(response.data);

我的代码:

import axios, { AxiosResponse } from "axios";
import { useEffect, useState } from "react";

const useRequest = (promise: Promise<AxiosResponse<any>>) => {
  const [loading, setLoading] = useState<boolean>(true);

  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        setError(null);
        await promise;
        setLoading(false);
        setError(null);
      } catch (error) {
        setLoading(false);
        setError("Error: " + JSON.stringify(error));
      }
    };
    fetchData();
  }, [promise]);

  return [loading, error];
};

export default function App() {
  const [data, setData] = useState<any | null>(null);

  const [loading, error] = useRequest(async () => {

    const response = await axios.get("https://jsonplaceholder.typicode.com/todos");
    setData(response.data);
    return response;
  });

  if (loading) {
    return <p>Loading ...</p>;
  } else if (data) {
    return <p>{data}</p>;
  } else {
    return <p>Error: {error}</p>;
  }
}

标签: reactjstypescriptaxiosreact-hooks

解决方案


您可以传递一个包含在 useCallback 钩子中的函数,该函数将调用您的 api 调用:

import axios, { AxiosResponse } from "axios";
import { useCallback, useEffect, useState } from "react";

const url = "https://jsonplaceholder.typicode.com/todos"

const useRequest = (apiCall: () => Promise<AxiosResponse<any>>, setData: (data: any) => void) => {
  const [loading, setLoading] = useState<boolean>(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        setError(null);
        const response = await apiCall()
        setData(response.data)
        setLoading(false);
        setError(null);
      } catch (error) {
        setLoading(false);
        setData(null)
        setError("Error: " + JSON.stringify(error));
      }
    };
    fetchData();
  }, [apiCall, setData]);

  return [loading, error];
};

export default function App() {
  const [data, setData] = useState<any | null>(null);
  const fun = useCallback(() => axios.get(url), [])

  const [loading, error] = useRequest(fun, setData);

  if (loading) {
    return <p>Loading ...</p>;
  } else if (data) {
    return <p>{'data'}</p>;
  } else {
    return <p>Error: {error}</p>;
  }
}

推荐阅读