在异步请求函数中使用UseDispatch Hook报错,求解决方案
问题原因
你遇到的错误是因为React Hook只能在React组件函数或自定义Hook的顶层调用,而fetchService是普通异步函数,直接使用useAppDispatch违反了Hook的使用规则。
解决方案
方案1:将dispatch作为参数传入fetchService
修改fetchService的参数定义,把组件中获取的dispatch传递进来使用:
const fetchService: ({}: { token?: string url: string method?: string addContentTypeApplicationJson?: boolean body?: any formData?: any options?: any dispatch: ReturnType<typeof useAppDispatch> }) => Promise<{ data: any; status: number }> = async ({ token = '', url, method = 'GET', body = {}, dispatch, }) => { let status: number const headers: any = { 'end-username': UserService.getUsername(), Authorization: 'Bearer ' + token, } dispatch(toggleLoading()) try { const response = await fetch(url, { method: method, headers: headers, body: body, }) status = response.status const responseJson = await response.json() dispatch(toggleLoading()) return { status: status, data: responseJson } } catch (e) { toast.error('Network Error!') dispatch(toggleLoading()) return { status: 500, data: {} } } } export { fetchService }
组件中调用示例:
const dispatch = useAppDispatch() // 调用fetchService fetchService({ url: '/api/example', method: 'POST', body: { key: 'value' }, dispatch: dispatch })
方案2:封装为自定义Hook
把请求逻辑放到自定义Hook中,这样就能合法使用useAppDispatch:
// 自定义Hook export const useFetchService = () => { const dispatch = useAppDispatch() const fetchData = async ({ token = '', url, method = 'GET', body = {}, }: { token?: string url: string method?: string body?: any }): Promise<{ data: any; status: number }> => { let status: number const headers: any = { 'end-username': UserService.getUsername(), Authorization: 'Bearer ' + token, } dispatch(toggleLoading()) try { const response = await fetch(url, { method: method, headers: headers, body: body, }) status = response.status const responseJson = await response.json() dispatch(toggleLoading()) return { status: status, data: responseJson } } catch (e) { toast.error('Network Error!') dispatch(toggleLoading()) return { status: 500, data: {} } } } return { fetchData } }
组件中使用示例:
const { fetchData } = useFetchService() const handleFetch = async () => { const result = await fetchData({ url: '/api/example', method: 'POST', body: { key: 'value' } }) // 处理请求结果 }
方案3:直接使用Redux Store实例
如果你的Redux Store是单独导出的(比如在store.ts中),可以直接导入并调用dispatch:
假设store.ts代码:
import { configureStore } from '@reduxjs/toolkit' import configReducer from './configSlice' export const store = configureStore({ reducer: { appConfigs: configReducer, }, }) export type RootState = ReturnType<typeof store.getState> export type AppDispatch = typeof store.dispatch
修改fetchService:
import { store } from './store' import { toggleLoading } from './configSlice' const fetchService: ({}: { token?: string url: string method?: string addContentTypeApplicationJson?: boolean body?: any formData?: any options?: any }) => Promise<{ data: any; status: number }> = async ({ token = '', url, method = 'GET', body = {}, }) => { let status: number const headers: any = { 'end-username': UserService.getUsername(), Authorization: 'Bearer ' + token, } store.dispatch(toggleLoading()) try { const response = await fetch(url, { method: method, headers: headers, body: body, }) status = response.status const responseJson = await response.json() store.dispatch(toggleLoading()) return { status: status, data: responseJson } } catch (e) { toast.error('Network Error!') store.dispatch(toggleLoading()) return { status: 500, data: {} } } } export { fetchService }
方案选择建议
- 方案1:适合需要保持
fetchService独立的场景,灵活度高; - 方案2:符合React Hook设计理念,适合在组件内复用请求逻辑;
- 方案3:实现最简单,但服务端渲染(SSR)场景需谨慎使用。
内容的提问来源于stack exchange,提问作者Mohammad Koolivand
相关产品推荐
相关产品推荐

