无法在回调中调用 React Hook

React Hook cannot be called inside a callback

问题陈述:

我正在尝试设置一个 React 组件,只要从 select 框中输入 select 值,它就会发出 API 调用。 我试图在 useEffect 挂钩中做到这一点,但我收到了基于挂钩规则的错误,我们不能在回调中调用任何挂钩。你能告诉我如何解决这个问题并对任何用户输入执行所需的 API 调用吗?

我正在查看可以帮助我防止此错误的指针,同时对后端进行 API 调用以获取记录

这是我的代码:

组件


const component: React.FC<ComponentProps> = () => {
  const { user } = useAppSelector((state) => state.auth);
  const periods = getPeriodNames();

  const [selectedPeriod, setSelectedPeriod] = React.useState(periods[0]);
  const [records, setRecords] = React.useState([]);
  const [columns, setColumns] = React.useState<any>();

  React.useEffect(() => {
    const [request] = React.useState<Request>({ // Throwing error:  React Hook "React.useState" cannot be called inside a callback.
      requester: user.alias,
      accountingMonth: selectedPeriod,
      limit: 300,
    });
    const { data, error, isLoading, isSuccess, isError } =
      useQuery(request); // Throwing error : React Hook "useQuery" cannot be called inside a callback.
    setRecords(data?.value);
  }, [selectedPeriod, user.alias]);

  const onPeriodSelect = (detail: SelectProps.ChangeDetail) => {
    setSelectedPeriod(selectedOption);
  };

  React.useEffect(() => {
    if (records) {
      // do something
    }
  }, [records]);

  return (
    <>
      <Select
        selectedOption={selectedPeriod}
        onChange={({ detail }) => onPeriodSelect(detail)}
        options={periods}
        selectedAriaLabel="Selected"
      />
    </>
  );
};

进行API呼叫的设置


export const dynamicBaseQuery: BaseQueryFn<
  string | FetchArgs,
  unknown,
  FetchBaseQueryError
> = async (args, api, extraOptions) => {
  const { mainApiUrl } = (api.getState() as RootState).settings.endpoints;
  const rawBaseQuery = fetchBaseQuery({
    baseUrl: mainApiUrl,
    prepareHeaders: (headers, { getState }) => {
      // Use getState to pull the jwtToken and pass it in the headers to the api endpoint.
      const { jwtToken } = (getState() as RootState).auth;
      headers.set("authorization", jwtToken);

      return headers;
    },
  });
  return rawBaseQuery(args, api, extraOptions);
};

export const mainApi = createApi({
  reducerPath: "mainApi",
  baseQuery: dynamicBaseQuery,
  endpoints: () => ({}),
});

const useQuery = mainApi.injectEndpoints({
  endpoints: (builder) => ({
    query: builder.query<response, request>({
      query: (request?: request) => ({
        url: "/test_url",
        body: request,
        method: "POST",
      }),
    }),
  }),
  overrideExisting: false,
});

任何帮助将不胜感激。谢谢

您可以将 API 调用放在回调中,然后在选择框处理程序中调用它。

示例:

const apiCall = (item) => {
  // api call logic
}

const handleSelectBox = (selectedItem)=> {
  apiCall(selectedItem)
}

如错误所述,您应该将自定义挂钩 useQuery 移出 useEffect

您可以将其添加到您的组件之上,而不是像下面这样

const component: React.FC<ComponentProps> = () => {
  const { user } = useAppSelector((state) => state.auth);
  const [request, setRequest] = React.useState<Request | undefined>();
  const periods = getPeriodNames();
  const { data, error, isLoading, isSuccess, isError } =
      useQuery(request); //when component get re-rendered, and request state is there, it will fetch data


  const [selectedPeriod, setSelectedPeriod] = React.useState(periods[0]);
  const [records, setRecords] = React.useState([]);
  const [columns, setColumns] = React.useState<any>();

  //fetched successfully
  React.useEffect(() => {
    if(data) {
       setRecords(data.value);
    }
  }, [data])

  React.useEffect(() => {
    setRequest({
      requester: user.alias,
      accountingMonth: selectedPeriod,
      limit: 300,
    })
  }, [selectedPeriod, user.alias]);

  const onPeriodSelect = (detail: SelectProps.ChangeDetail) => {
    setSelectedPeriod(selectedOption);
  };

  React.useEffect(() => {
    if (records) {
      // do something
    }
  }, [records]);

  return (
    <>
      <Select
        selectedOption={selectedPeriod}
        onChange={({ detail }) => onPeriodSelect(detail)}
        options={periods}
        selectedAriaLabel="Selected"
      />
    </>
  );
};