【问题标题】:How can I make my axios function reusable in other React/Typescript components?如何使我的 axios 函数在其他 React/Typescript 组件中可重用?
【发布时间】:2021-01-20 15:54:41
【问题描述】:

我正在复制/粘贴相同的代码以在多个组件中发出 axios 请求,如下所示:

React.useEffect(() => {
    axios
        .get<IDownloads[]>(`${process.env.PUBLIC_URL}/api/downloads`, {

        headers: {
          'Content-Type': 'application/json',
        },
        timeout: 5000,
      })
      .then((response) => {
        setFaqs(response.data);
      })
      .catch((ex) => {
        const err = axios.isCancel(ex)
          ? 'Request cancelled'
          : ex.code === 'ECONNABORTED'
            ? 'A timeout has occurred'
            : ex.response.status === 404
              ? 'Resource not found'
              : 'An unexpected error has occurred';
        setError(err);
      });

  }, []);

有效,但不遵循 DRY。我希望能够在我的应用程序的其他区域重用此代码,但需要能够更改 .get(${process.env.PUBLIC_URL}/api/downloads 以在其他区域工作。例如 .get(@ 987654323@我做了一个新组件试图做到这一点

export default function useApiRequest<T>(url: string): { response: T | null; error: Error | null} {
   const [response, setResponse] = React.useState<T | null>(null);
   
    const [error, setError] = React.useState<Error | null>(null);
  
    React.useEffect(() => {
      const fetchData = async (): Promise<void> => {
       try {
           const res = await axios(`${process.env.PUBLIC_URL}${url}`);
           setResponse(res.data);
       } catch (error) {
           setError(error);
       }
    };
    fetchData();
}, [url]);
  
    return { response, error };
  };

并像这样在这个组件中使用它:

interface IDownloads {
  db_id: number;
  file_description: string;
  file_name: string;
  developer_name: string;
  date_uploaded: string;
  file_url: string;
}

const defaultProps: IDownloads[] = [];

const DownloadCodeSamplesPage: React.FC = () => {

  const downloadQuery = useApiRequest<IDownloads[]>('/api/download');
 
  const [downloads, setDownloads]: [IDownloads[], (posts: IDownloads[]) => void] =
    React.useState(defaultProps);

在我返回时,我正在像这样映射下载


                  downloads.map((download) => (
                    <tr key={download.db_id}>
                      <td>{download.file_description}</td>
                      <td>{download.file_name}</td>
                      <td>{download.developer_name}</td>
                      <td>{download.date_uploaded}</td>

当我运行程序时,我没有收到来自 api 调用的任何数据。我做错了什么?

【问题讨论】:

    标签: reactjs typescript axios refactoring dry


    【解决方案1】:

    状态重复

    你的钩子看起来很棒。问题在于您如何在组件中使用它。 downloads 不需要本地状态——这就是关键所在!所以杀掉那个React.useState 和你打电话给setDownloads 的任何地方。

    您可以从钩子中访问downloads,如果它是null,则将其替换为空数组。

    const downloads = downloadQuery.response ?? [];
    
    const DownloadCodeSamplesPage: React.FC = () => {
      const downloadQuery = useApiRequest<IDownloads[]>("/api/download");
    
      const downloads = downloadQuery.response ?? [];
    
      return (
        <table>
          <tbody>
          {downloads.map((download) => (
            <tr key={download.db_id}>
              <td>{download.file_description}</td>
              <td>{download.file_name}</td>
              <td>{download.developer_name}</td>
              <td>{download.date_uploaded}</td>
            </tr>
          ))}
        </tbody>
        </table>
      );
    };
    

    您可以考虑为您的网站创建一个 axios instance,该网站预先配置了 baseUrl 和任何其他设置,并在您的应用中随处使用。

    【讨论】:

      猜你喜欢
      • 2019-09-09
      • 2019-09-08
      • 1970-01-01
      • 1970-01-01
      • 2021-10-07
      • 2019-06-27
      • 1970-01-01
      • 2021-01-03
      • 2020-10-13
      相关资源
      最近更新 更多