TanStack Query

373 阅读2分钟

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)
  }, [])


image.png 可以看到里面有一些数据信息。

  • 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 }, }, 
});

我们把路径改一下 显示错误路径

image.png

则看到 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 获取下一页的数据

image.png

乐观更新

乐观更新就是在没有从服务器得到响应之前,先更新用户界面

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>
)

image.png

image.png

  • isIdle或status === 'idle' - 突变当前处于空闲状态或处于刷新/重置状态
  • isPending或status === 'pending' - 突变目前正在运行
  • isError或status === 'error' - 突变遇到错误
  • isSuccess或status === 'success' - 突变成功且突变数据可用
  • reset() 重置