SetState 依赖于 API 响应导致 - 重新渲染错误太多

SetState dependent on API response is causing - Too many re-render error

在下面的代码中,我尝试将 stop 的状态设置为 true,以便根据特定代码通过 useQuery 响应来自特定 API 的响应,我可以开始轮询 API。默认情况下,轮询仍然是假的。

我的问题是如何在此处设置状态,而不反应抛出 Too many re-renders error

问题文件

import React, { useState } from 'react';
import { Navigate, useLocation } from 'react-router-dom';
import { useBffQueryApi } from '../hooks/useQueryBffApi';
import {
  appStatus,
  IStatusAPIResponse,
  IHeaderInformation,
} from '../api/appStatus';
import { useAppSelector } from '../app/hooks';
import { RootState } from '../app/store';
// import { MobileNumber } from './features/ContactNumber/MobileNumber';

export function web() {
  const location = useLocation();
  const authzToken = useAppSelector(
    (state: RootState) => state.authz.AuthzInfo,
  );

  const [stop, setStop] = useState(true);

  const {
    data: response,
    error,
    isLoading,
  } = useBffQueryApi<IStatusAPIResponse, IHeaderInformation>(
    'status',
    () => appStatus({ auth: authzToken }),
    true,
    stop,
  );

  const redirecter = (status: number) => {

//Here lies the problem

    if (status === 306) {
      setStop(false);
      // Do something
    }

//Here lies the problem

    if (status === 41) {
      return <Navigate to="/web/email-confirmation" />;
    }

    if (status === 42) {
      return <Navigate to="/web/personal-details" />;
    }

    if (status === 44) {
      return <Navigate to="/web/address-details" />;
    }

    if (status === 50) {
      return <Navigate to="/web/offer-details" />;
    }

    if (status === 48) {
      return <Navigate to="/web/denied" />;
    }

    if (status === 51 || status === 52 || status === 53) {
      return <Navigate to="/web/offer-details" />;
    }

    if (status === 46) {
      return (
        <Navigate
          to="/web/third-party"
          state={{ location: location.pathname }}
        />
      );
    }

    if (status === 47) {
      return <Navigate to="/web/third-party" />;
    }

    return null;
  };

  if (isLoading) {
    return (
      <div>
        <h1>Loading</h1>
      </div>
    );
  }

  if (error?.response?.status === 401) {
    return <Navigate to="/web/phone" />;
  }

  const { status } = response!.data;

  return redirecter(status);
}

自定义挂钩

import { AxiosError, AxiosResponse } from 'axios';

export const useBffQueryApi = <J, K>(
  cacheIdentity: string | Array<string | K>,
  fn: QueryFunction<AxiosResponse<J>>,
  enabled: boolean = true,
  stop: boolean = true,
) => {
  return useQuery<AxiosResponse<J>, AxiosError>(cacheIdentity, fn, {
    retry: 0,
    cacheTime: 0,
    enabled,
    refetchInterval: stop ? false : 5000,
  });
};

render时不能调用setState,违反了react的规则。你在这里这样做:

if (status === 306) {
  setStop(false);
  // Do something
}

副作用需要转到 useEffect,或者,您可以使用 useQuery.

提供的 onSuccessonError 回调

对于你的情况,你不一定需要本地状态,因为 refetchInterval 也可以是一个函数:

useQuery(
  key,
  fn,
  {
    refetchInterval: (data) => !data || data.status === 306 ? false : 5000
  }
)