无法在回调中调用 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"
/>
</>
);
};
问题陈述:
我正在尝试设置一个 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"
/>
</>
);
};