1. 安装
QueryClientProvider配置
function App() {
const queryClient = new QueryClient()
return (
<>
<QueryClientProvider client={queryClient}>
<RouterProvider router={router} />
</QueryClientProvider>
<QueryClientProvider client={queryClient}>
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
</>
)
}
export default App
全局配置QueryClientProvider 之后在useQueryClient才可以拿到实例,在ReactQueryDevtools可以看到一些调试的信息
2. 查询(Query)
查询代表从某个地方获取数据,而突变则代表发起数据变更操作(如增加、修改、删除等)。
TanStack Query 使用了两个变量来维护请求相关的状态,status 用来描述是否请求到了数据。 fetchStatus 用来描述 queryFn 是否正在执行中。
正好之前写nest有用户信息的接口,那我们写个查询的例子测试一下
const result = useQuery({
queryKey: ['useList'],
queryFn: () =>
UserAPI.getUserLists({
page: 1,
pageSize: 10
})
})
useEffect(() => {
console.log(result)
}, [])
可以看到里面有一些数据信息。
data:请求返回的数据。error:请求失败时对应的错误对象。isPending/status === 'pending':还没有数据。isError/status === 'error':请求出错了。isSuccess/status === 'success':请求成功并且数据可用状态。isFetching/fetchStatus === 'fetching':正在请求数据中。isPaused/fetchStatus === 'paused':请求暂停中。fetchStatus === 'idle':当前没有任何请求,处于空闲中。
queryKey 是一个数组,会基于queryKey来管理缓存,并在依赖项更新时自动触发重新获取。TanStack Query 会对 Query Keys 进行哈希处理,将数组计算成一个值作为该 Query的映射 如果值一致就用缓存
默认配置项
重试次数 retry:4 等待延时时间
const queryClient = new QueryClient(
{
defaultOptions: { queries: { retry:4,retryDelay: 2000 }, },
});
我们把路径改一下 显示错误路径
则看到 TanStack Query 自动帮我们重试 4 次
使用场景
预加载
const prefetch = () => {
queryClient.prefetchQuery({
queryKey: ['useList'],
queryFn: fetchData,
staleTime: 60000
})
}
取消加载
TanStack Query 提供的 signal 来设置请求取消 原理也是用到AbortController
const result = useQuery({
queryKey: ['useList'],
queryFn: ({ signal }) =>
UserAPI.getUserLists(
{
page: 1,
pageSize: 10
},
signal
)
})
无限查询
const { data, fetchNextPage, hasNextPage, isFetchingNextPage } = useInfiniteQuery({
queryKey: ['useList'],
queryFn: ({ pageParam }) => fetchData(pageParam),
initialPageParam: 1,
getNextPageParam: (lastPage, allPages) => {
const nextPage = allPages.length + 1
return nextPage
}
})
- fetchNextPage 获取下一页的数据
乐观更新
乐观更新就是在没有从服务器得到响应之前,先更新用户界面
3 Mutation
Mutation通常用于创建/更新/删除数据 一个例子
export function Component() {
const [username, setUsername] = useState('')
const mutation = useMutation({
mutationFn: (newTodo) => {
console.log(newTodo)
return UserAPI.addUser({
username,
password: '123456'
})
},
onMutate: (variables) => {
//发送请求前执行的函数
return { id: 1 }
},
onError: (error, variables, context) => {
//失败的时候 context 为 { id: 1 }
},
onSuccess: (data, variables, context) => {
//成功执行的函数 context 为 { id: 1 }
},
onSettled: (data, error, variables, context) => {
//无论成功和失败都执行的函数 context 为 { id: 1 }
}
})
return (
<div className=" h-full">
<Button onClick={() => mutation.mutate()}>添加用户</Button>
<Input
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
</div>
)
- isIdle或status === 'idle' - 突变当前处于空闲状态或处于刷新/重置状态
- isPending或status === 'pending' - 突变目前正在运行
- isError或status === 'error' - 突变遇到错误
- isSuccess或status === 'success' - 突变成功且突变数据可用
- reset() 重置