React 18 结合 React Query 5:数据请求缓存与状态管理实践

1. 核心概念
  • React 18 新特性
    并发渲染(Concurrent Rendering)、自动批处理(Automatic Batching)、Suspense 组件优化
  • React Query 核心功能
    自动缓存管理、请求去重、后台数据刷新、错误重试机制
    状态管理公式(缓存新鲜度):
    $$ \text{缓存有效性} = f(\text{staleTime}, \text{cacheTime}, \text{refetchInterval}) $$
2. 基础配置
# 安装依赖
npm install react@18 react-dom@18 @tanstack/react-query@5

// src/index.js
import React from 'react';
import { createRoot } from 'react-dom/client';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 5 * 60 * 1000, // 5分钟缓存有效期
      retry: 2, // 失败自动重试2次
    }
  }
});

createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <QueryClientProvider client={queryClient}>
      <App />
    </QueryClientProvider>
  </React.StrictMode>
);

3. 数据请求实践
// 数据获取 Hook
import { useQuery } from '@tanstack/react-query';

const fetchProjects = async () => {
  const res = await fetch('/api/projects');
  if (!res.ok) throw new Error('请求失败');
  return res.json();
};

export const useProjects = () => {
  return useQuery({
    queryKey: ['projects'], // 唯一缓存标识
    queryFn: fetchProjects,
    // React 18 Suspense 集成
    suspense: true,
    // 后台自动刷新(单位:毫秒)
    refetchInterval: 10 * 1000 
  });
};

4. 组件集成示例
// 项目列表组件
import { Suspense } from 'react';
import { useProjects } from './hooks';

const ProjectList = () => {
  const { data } = useProjects(); // 自动处理缓存

  return (
    <ul>
      {data.map(project => (
        <li key={project.id}>
          {project.name} - 状态: {project.status}
        </li>
      ))}
    </ul>
  );
};

// 使用 Suspense 处理加载状态
const App = () => (
  <Suspense fallback={<div>加载中...</div>}>
    <ProjectList />
  </Suspense>
);

5. 数据变更与缓存更新
// 数据提交 Hook
import { useMutation, useQueryClient } from '@tanstack/react-query';

const useCreateProject = () => {
  const queryClient = useQueryClient();
  
  return useMutation({
    mutationFn: (newProject) => 
      fetch('/api/projects', {
        method: 'POST',
        body: JSON.stringify(newProject)
      }),
    // 成功时自动刷新缓存
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['projects'] });
    },
    // 乐观更新(React 18 批处理优化)
    onMutate: async (newProject) => {
      await queryClient.cancelQueries(['projects']);
      const prev = queryClient.getQueryData(['projects']);
      queryClient.setQueryData(['projects'], old => [...old, newProject]);
      return { prev };
    },
    onError: (err, vars, context) => {
      queryClient.setQueryData(['projects'], context.prev);
    }
  });
};

6. 高级优化策略
  1. 请求合并
    相同 queryKey 的并发请求自动合并为单次请求
  2. 分页缓存
    useQuery({
      queryKey: ['projects', { page: 2 }],
      queryFn: () => fetchPage(2),
      keepPreviousData: true // 保留上一页数据
    })
    

  3. 依赖请求
    const { data: user } = useQuery(['user', userId]);
    const projects = useQuery({
      queryKey: ['projects', user.id],
      queryFn: () => fetchUserProjects(user.id),
      enabled: !!user.id // 依赖生效后才触发
    });
    

7. 开发工具集成
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';

function App() {
  return (
    <>
      {/* 主应用内容 */}
      <ReactQueryDevtools 
        initialIsOpen={false} 
        position="bottom-right" 
      />
    </>
  );
}

  • 可视化查看缓存状态
  • 手动触发缓存刷新
  • 模拟网络错误测试
最佳实践建议
  1. 缓存策略
    • 高频更新数据:设置较短的 staleTime(如 $10 \text{秒}$)
    • 静态数据:延长 cacheTime(如 $24 \text{小时}$)
  2. 错误处理
    使用全局 onError 回调统一处理异常
  3. 性能监控
    结合 React 18 的 <Profiler> 组件分析渲染性能
  4. 服务端渲染
    通过 dehydrate/hydrate 实现 SSR 数据预取

关键优势:React Query 将请求状态(加载/成功/错误)与业务状态解耦,配合 React 18 的并发渲染能力,可减少约 $40%$ 的不必要渲染,显著提升复杂应用性能。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐