React Query:高效管理API请求与缓存

React Query 是一个强大的状态管理库,专门用于处理数据获取、缓存和更新,尤其适合与 API 交互。它提供了许多高级特性,如自动缓存、离线状态管理、数据过期和重新获取等。

安装:

   npm install react-query

导入并配置 React Query:

在你的应用中,你需要导入 useQuery Hook 并设置配置对象。

   import { useQuery } from 'react-query';

   const queryClient = new QueryClient();

可以通过 QueryClientProviderqueryClient 包裹在你的根组件周围,以便在整个应用中使用。

   import { QueryClient, QueryClientProvider } from 'react-query';
   
   const queryClient = new QueryClient();

   function App() {
     return (
       <QueryClientProvider client={queryClient}>
         {/* Your application */}
       </QueryClientProvider>
     );
   }

使用 useQuery Hook:

使用 useQuery 来发起 API 请求并管理响应数据。

   function MyComponent() {
     const { data, status, error } = useQuery('myQueryKey', () => fetch('https://api.example.com/data'));

     if (status === 'loading') return 'Loading...';
     if (error) return 'An error occurred.';
     return <div>{data}</div>;
   }

这里,myQueryKey 是查询的唯一标识符,fetch('https://api.example.com/data') 是实际的 API 调用。

配置选项:

useQuery 接受一个配置对象,可以设置缓存策略、重试逻辑等。

   const { data } = useQuery(
     'myQueryKey',
     () => fetch('https://api.example.com/data'),
     {
       staleTime: 60000, // 数据在多久后被视为过期并重新获取
       retry: 3, // 重试次数
       refetchOnWindowFocus: false, // 窗口聚焦时是否重新获取数据
     }
   );

手动操作:

你可以手动触发数据的重新获取、取消或设置为错误状态。

   const { refetch, reset, isFetching } = useQuery('myQueryKey', fetchData);

   // 重新获取数据
   refetch();

   // 清除查询状态和数据
   reset();

   // 检查是否正在获取数据
   if (isFetching) console.log('Data is being fetched');

订阅更新:

你可以通过 useQuery 的返回值订阅查询状态变化。

   const { status, data, error } = useQuery('myQueryKey', fetchData);
   useEffect(() => {
     if (status === 'success') console.log('Data updated:', data);
   }, [status, data]);

分页:

React Query 支持分页,你可以通过 useInfiniteQuery Hook 实现无限滚动。

   import { useInfiniteQuery } from 'react-query';

   function MyInfiniteList() {
     const { data, isFetching, hasNextPage, fetchNextPage } = useInfiniteQuery(
       'myInfiniteQuery',
       async ({ pageParam = 1 }) => {
         const response = await fetch(`https://api.example.com/data?page=${pageParam}`);
         return response.json();
       },
       {
         getNextPageParam: (lastPage) => lastPage.nextPageToken || false,
       }
     );

     return (
       <div>
         {data.pages.map((page, index) => (
           <ul key={index}>{page.items.map(item => <li key={item.id}>{item.title}</li>)}</ul>
         ))}
         {hasNextPage && !isFetching && (
           <button onClick={fetchNextPage}>Load More</button>
         )}
       </div>
     );
   }

这里,getNextPageParam 函数用于从上一页的响应中提取下一页的标识符。

缓存更新:

当 API 数据更新时,React Query 可以自动更新缓存中的数据,例如在使用 Mutation 时。

   import { useMutation } from 'react-query';

   const [updateItem] = useMutation(async (updatedItem) => {
     await fetch('https://api.example.com/items/' + updatedItem.id, {
       method: 'PUT',
       body: JSON.stringify(updatedItem),
     });
   });

   // 更新数据并自动刷新相关查询
   updateItem.mutate(updatedItem);

错误处理:

React Query 提供了内置的错误处理机制,你可以通过 error 属性来捕获错误。

   const { data, error } = useQuery('myQueryKey', fetchData);

   if (error) return <div>Error: {error.message}</div>;

查询缓存清理:

你可以根据需要清理特定查询的缓存。

    queryClient.removeQueries('myQueryKey'); // 清理所有匹配的查询
    queryClient.cancelQueries('myQueryKey'); // 取消匹配的查询

自定义中间件:

通过自定义中间件,你可以扩展 React Query 的功能,例如添加日志、性能监控等。

    import { QueryClient, QueryClientProvider } from 'react-query';

    const queryClient = new QueryClient({
      queryCache: new QueryCache({
        middlewares: [
          // 自定义中间件
          myCustomMiddleware,
        ],
      }),
    });

预取数据(Prefetching):

React Query 允许你在组件渲染之前预取数据,提升用户体验。

    import { usePrefetch } from 'react-query';

    function MyComponent() {
      const prefetchData = usePrefetch('myQueryKey');

      useEffect(() => {
        // 在组件挂载时预取数据
        prefetchData();
      }, []);

      // ...其他逻辑
    }

乐观更新(Optimistic Updates):

在用户触发变更操作时立即更新 UI,然后再等待服务器确认,这能提供即时反馈,提升交互体验。

    import { useMutation } from 'react-query';

    const [updateTodo, { optimisticData }] = useMutation(updateTodoMutation, {
      onMutate: (newTodo) => {
        // 乐观地更新客户端缓存
        queryClient.setQueryData(['todos', newTodo.id], newTodo);
        return { previousTodo: queryClient.getQueryData(['todos', newTodo.id]) };
      },
      onError: (err, newTodo, context) => {
        // 如果发生错误,回滚到之前的值
        queryClient.setQueryData(['todos', newTodo.id], context.previousTodo);
      },
      onSettled: () => {
        // 查询已解决时,可以做清理工作
        queryClient.invalidateQueries('todos');
      },
    });

    function handleUpdate(todo) {
      updateTodo({ ...todo, completed: !todo.completed });
    }

并发控制:

有时,你需要控制同时运行的查询数量,特别是当调用多个 API 或有大量并发请求时。

    const { data } = useQuery(['concurrentQuery', { limit: 10 }], fetchItems, {
      staleTime: Infinity, // 防止数据过期自动重试
      refetchInterval: false, // 关闭自动轮询
      refetchOnWindowFocus: false, // 不在窗口聚焦时自动重试
      retry: false, // 失败时不重试
      useErrorBoundary: true, // 错误边界,避免组件树崩溃
      concurrency: 2, // 最大并发数
    });

依赖注入:

如果你的查询逻辑依赖于外部参数,可以通过 useQueries 来并行执行多个查询,每个查询可以有不同的配置。

    import { useQueries } from 'react-query';

    function MyComponent({ ids }) {
      const queries = useQueries(
        ids.map(id => ({
          queryKey: ['item', id],
          queryFn: () => fetchItem(id),
        }))
      );

      return (
        <div>
          {queries.map(query => (
            <div key={query.queryKey[1]}>
              {query.isLoading ? 'Loading...' : query.data?.title}
            </div>
          ))}
        </div>
      );
    }

React Query 的设计考虑到了现代 Web 应用的各种复杂场景,通过上述功能,开发者可以轻松实现数据管理和状态同步,同时保持应用的高性能和良好的用户体验。

2500G计算机入门到高级架构师开发资料超级大礼包免费送!

  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天涯学馆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值