首页 / React 19 入门教程 / 数据请求库

React 19 入门教程

数据请求库

本教程共 50 篇 · 第 36 篇 · 更新于 2026-07-29 · 约 7 分钟阅读

ReactSWRTanStack Query数据请求缓存React Query

36. 数据请求库

本节目标:理解为什么需要数据请求库,上手 SWR 和 TanStack Query 的基本用法,知道它们解决什么问题。

上一章那个 Hook 缺了什么

我们在上一章手写了 useFetch。它能跑,但离生产级还差不少:

  • 没有缓存:组件销毁再挂载,重新发请求
  • 没有去重:同一页面多个组件请求同一个 URL,各自发各的
  • 没有自动重验证:窗口重新获得焦点时不会刷新数据
  • 没有分页/无限加载支持
  • 没有乐观更新

自己写这些能写到怀疑人生。社区早就有成熟方案了。

SWR:先试试水

SWR(stale-while-revalidate)是 Vercel 出的一套轻量数据请求 Hook。名字来自一种缓存策略:先用缓存数据,后台重新验证,拿到新数据再更新。

npm install swr

基本用法:

import useSWR from 'swr';

const fetcher = url => fetch(url).then(res => res.json());

function UserProfile({ userId }) {
  const { data, error, isLoading } = useSWR(
    `/api/users/${userId}`,
    fetcher
  );

  if (isLoading) return <p>加载中……</p>;
  if (error) return <p>出错了</p>;
  return <h1>{data.name}</h1>;
}

就两行配置,自动帮你搞定:缓存、去重、聚焦重验证、轮询。

Note

useSWR 的第一个参数是 key。key 变化就会重新请求。多个组件用同一个 key,只会发一次请求。

SWR 的配置

可以全局配置 fetcher 和默认行为:

import { SWRConfig } from 'swr';

function App() {
  return (
    <SWRConfig value={{
      fetcher: url => fetch(url).then(res => res.json()),
      revalidateOnFocus: true,    // 窗口聚焦时重验证
      dedupingInterval: 5000,    // 5 秒内重复请求去重
      errorRetryCount: 3,        // 失败后重试 3 次
    }}>
      <UserProfile userId={1} />
    </SWRConfig>
  );
}

SWR 的 mutation

需要手动触发重新验证时,用 mutate

import { useSWRConfig } from 'swr';

function RefreshButton() {
  const { mutate } = useSWRConfig();
  return (
    <button onClick={() => mutate('/api/users/1')}>
      刷新
    </button>
  );
}

TanStack Query:重武器

TanStack Query(原名 React Query)功能更全,适合复杂场景。

npm install @tanstack/react-query

基本用法:

import { QueryClient, QueryClientProvider, useQuery } from '@tanstack/react-query';

const queryClient = new QueryClient();

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <UserProfile userId={1} />
    </QueryClientProvider>
  );
}

function UserProfile({ userId }) {
  const { data, isLoading, error } = useQuery({
    queryKey: ['user', userId],
    queryFn: async () => {
      const res = await fetch(`/api/users/${userId}`);
      if (!res.ok) throw new Error('请求失败');
      return res.json();
    },
  });

  if (isLoading) return <p>加载中……</p>;
  if (error) return <p>出错了:{error.message}</p>;
  return <h1>{data.name}</h1>;
}

两个关键概念:queryKeyqueryFn。queryKey 是缓存的标识,变化就重新请求。

Tip

queryKey 用数组形式 ['user', userId],可以精确控制缓存粒度。所有用相同 queryKey 的请求共享缓存。

TanStack Query 的 mutation

更新数据用 useMutation

import { useMutation, useQueryClient } from '@tanstack/react-query';

function UpdateNameForm({ userId }) {
  const queryClient = useQueryClient();
  const mutation = useMutation({
    mutationFn: async newName => {
      const res = await fetch(`/api/users/${userId}`, {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ name: newName }),
      });
      return res.json();
    },
    onSuccess: () => {
      // 成功后让相关缓存失效,自动重新请求
      queryClient.invalidateQueries({ queryKey: ['user', userId] });
    },
  });

  return (
    <button
      disabled={mutation.isPending}
      onClick={() => mutation.mutate('新名字')}
    >
      {mutation.isPending ? '保存中……' : '保存'}
    </button>
  );
}

两个库的对比

特性SWRTanStack Query
体积~4KB~13KB
学习曲线
缓存策略内置高度可配
分页/无限加载有 (useSWRInfinite)有 (useInfiniteQuery)
DevTools简单功能全
乐观更新手动内置支持
离线支持较弱较强

我的建议:简单项目用 SWR,够用且轻量。复杂项目、需要精细控制缓存、频繁做 mutation 的,上 TanStack Query。

Warning

这两个库都基于 Suspense 边界做了 React 19 适配。如果你已经在用 React 19 的 use Hook,很多场景下可能不需要额外的请求库了。

数据请求的通用套路

不管用哪个库,数据请求都遵循这几个套路:

  1. 请求成功 → 展示数据
  2. 请求中 → 显示加载态(spinner 或骨架屏)
  3. 请求失败 → 显示错误 + 重试按钮
  4. 数据过期 → 后台重新验证,不打断用户

手动写这些逻辑不难,但到处重复就烦了。请求库帮你把样板代码吃掉,你专注业务就行。

React 19 的 use Hook 来了

React 19 引入了 use Hook,可以在组件里直接读取 Promise:

import { use, Suspense } from 'react';

function Albums({ albumsPromise }) {
  const albums = use(albumsPromise);
  return (
    <ul>
      {albums.map(album => <li key={album.id}>{album.title}</li>)}
    </ul>
  );
}

function App() {
  return (
    <Suspense fallback={<p>加载中……</p>}>
      <Albums albumsPromise={fetchData('/albums')} />
    </Suspense>
  );
}

这是 React 官方的数据获取方案,后面章节会详细讲。但 use 本身不提供缓存、重验证这些能力,所以和 SWR/TanStack Query 不是替代关系,是互补的。