组件使用自定义 axios 挂钩不断进行 api 次调用

Component keeps making api calls with custom axios hook

我有一个显示一些小部件的仪表板组件。它从四个不同的 API 中获取小部件数据。

Dashbaord.jsx

import { Box, Stack } from '@mui/material';
import { useAxios } from '../../api/use-axios';
import { NewWidget } from '../../components/widget/NewWidget';
import ApiConfig from '../../api/api-config';

const Dashboard = () => {
  const { response: studentResponse } = useAxios({
    url: ApiConfig.STUDENTS.base,
  });

  const { response: courseResponse } = useAxios({
    url: ApiConfig.COURSES.base,
  });

  const { response: feesResponse } = useAxios({
    url: ApiConfig.FEES.total,
  });

  return (
    <Box padding={2} width="100%">
      <Stack direction={'row'} justifyContent="space-between" gap={2} mb={10}>
        <NewWidget type={'student'} counter={studentResponse?.data?.length} />
        <NewWidget type={'course'} counter={courseResponse?.data?.length} />
        <NewWidget type={'earning'} counter={feesResponse?.data} />
        <NewWidget type={'teacher'} counter={studentResponse?.data?.length} />
      </Stack>
    </Box>
  );
};
export default Dashboard;

它使用自定义挂钩 useAxios 进行 API 调用。

使用-axios.jsx

import { useState, useEffect } from 'react';
import axios from 'axios';

axios.defaults.baseURL = 'http://localhost:3000';

export const useAxios = (axiosParams) => {
  const [response, setResponse] = useState(undefined);
  const [error, setError] = useState('');
  const [loading, setLoading] = useState(true);

  const fetchData = async (params) => {
    try {
      const result = await axios.request({
        ...params,
        method: params.method || 'GET',
        baseURL: 'http://localhost:3000',
        headers: {
          accept: 'application/json',
        },
      });
      setResponse(result.data);
    } catch (error) {
      setError(error);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    fetchData(axiosParams);
  }, [axiosParams]); // execute once only

  return { response, error, loading };
};

api-config.js

export default {
  COURSES: {
    base: '/courses',
  },
  FEES: {
    base: '/fees',
    total: '/fees/total',
  },
  STUDENTS: {
    base: '/students',
  },
};

但不知何故,它会继续呈现,所有响应也会形成 APIs,它会记录到 undefiend

我尝试从 useAxios 中的 useEffect 删除依赖项 axiosPamras,它停止发出多个请求但仍然显示 dependency warning 并且响应仍然是 undefined.


更新: undefined 错误已修复,我没有传递授权令牌。 :(

但是当 axiosParams 添加到依赖项时它仍然在循环中调用 apis


发生这种情况是因为您的呼叫方式 useAxios。您每次都传递一个对象文字,例如

const { response: studentResponse } = useAxios({
  url: ApiConfig.STUDENTS.base,
});

因为您正在调用一个对象,所以 this 的相等性由引用决定 - 传递一个对象文字是每个渲染器上的一个新引用,即使它是您所关注的“相同”对象.因此,以 axiosParams 作为其依赖项的 useEffect 每次都会重新运行,因此会重复发送请求。

在这种情况下,最简单的解决方案可能是将这些对象提取为存储在组件外部的常量 - 它们来自 ApiConfig 对象,因此当应用程序 [=30] 时,这似乎不太可能改变=].这样做意味着引用将始终相同,因此不会触发您的 useEffect 重新运行。

也就是把这个放在组件外面:

const STUDENT_AXIOS_CONFIG = { url: ApiConfig.STUDENTS.base };

另外两套axios参数也一样。然后在组件内部做:

const { response: studentResponse } = useAxios(STUDENT_AXIOS_CONFIG);

当然对其他 2 个调用也做同样的事情。