我正在开发一个 React 应用程序,其中使用 React-router 进行路由,使用 React-query 进行数据管理。我的目标是在react-router加载器函数中获取数据,但是我在从react-query访问isLoading和isError状态时遇到了问题。
API查询及Hook定义:
import { useQuery, UseQueryResult } from '@tanstack/react-query'
import { getDefaultValues } from './apiClient'
import { AxiosError } from 'axios'
export const useFetchDefaultValues = () => {
return useQuery({
queryKey: ['defaultValues'],
queryFn: () => getDefaultValues(),
})
}
export const getDefaultValues = async () => {
try {
const { data } = await axios.get(`${baseUrl}/pulse/getDefaultValues`)
return data
} catch (error) {
console.log(error)
throw new Error('Error fetching default values')
}
}
React 路由器加载器功能:
export const loader: LoaderFunction = async () => {
const { data: defaultData } = await useFetchDefaultValues()
return defaultData ? defaultData.results : []
}
import BreadCrumb from '@/components/BreadCrumb'
import DataTable from '@/components/DataGrid/DataTable'
import { fetchFulfilled } from '@/features/defaultValues/defaultValuesSlice'
import { useEffect } from 'react'
import { useAppDispatch } from '@/Hooks/hooks'
import { useLoaderData } from 'react-router-dom'
const ProgramOverviewPage = () => {
const defaultData = useLoaderData() as Parameter[]
const dispatch = useAppDispatch()
useEffect(() => {
if (defaultData) {
dispatch(fetchFulfilled(defaultData))
}
}, [defaultData, dispatch])
return (
<div className='flex flex-col gap-4 h-full'>
<div className=''>
<BreadCrumb page='T_Program_Overview' />
</div>
<div className='flex-1 p-6 overflow-hidden bg-background rounded-xl'>
<DataTable />
</div>
</div>
)
}
export default ProgramOverviewPage
问题:
当尝试在加载器内使用 useFetchDefaultValues 挂钩时,我收到以下错误:
Unexpected Application Error!
Cannot read properties of null (reading 'useContext')
TypeError: Cannot read properties of null (reading 'useContext')
at Object.useContext (http://.../react-query.js:1062:29)
...
在加载器中使用react-query钩子似乎不起作用,因为加载器在与React组件不同的上下文中运行。
在加载器中直接获取 API(可以工作,但缺少加载/错误状态处理):
import { defer, LoaderFunction } from 'react-router-dom'
import { getDefaultValues } from '@/api/apiClient'
export const loader: LoaderFunction = async () => {
const defaultDataPromise = getDefaultValues()
return defer({ defaultData: defaultDataPromise })
}
问题:当直接在加载器中获取 API 时,我成功获取了数据,但我无法访问 isLoading、isError 或其他 React Query 挂钩属性来有效管理 UI 状态。
问题:
如何在react-router加载器中正确使用react-query,同时避免useContext错误? 在加载器函数中执行 API 查询时,是否有推荐的方法来处理加载和错误状态? 如果在加载器中使用react-query不可行,那么在加载器中直接获取数据时如何有效处理加载和错误状态? 预先感谢您的帮助!
您无法访问 React Components 之外的钩子或自定义钩子。这些是 React 的 hooks 规则。钩子也不是异步的,所以你不能简单地
await
一个钩子。
我有一篇博客文章,用于将react-router与react-query集成,你想要做的是访问
queryClient
并在那里调用ensureQueryData
:
export const loader =
(queryClient) =>
async () => {
return queryClient.ensureQueryData({
queryKey: ['defaultValues'],
queryFn: () => getDefaultValues(),
})
}