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
.
提供的 onSuccess
或 onError
回调
对于你的情况,你不一定需要本地状态,因为 refetchInterval
也可以是一个函数:
useQuery(
key,
fn,
{
refetchInterval: (data) => !data || data.status === 306 ? false : 5000
}
)
在下面的代码中,我尝试将 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
.
onSuccess
或 onError
回调
对于你的情况,你不一定需要本地状态,因为 refetchInterval
也可以是一个函数:
useQuery(
key,
fn,
{
refetchInterval: (data) => !data || data.status === 306 ? false : 5000
}
)