React 服务端状态管理:用 TanStack Query 接管数据请求、缓存与重试

test12026-09-204 次阅读

把“服务端状态”从组件里剥离出来

组件里的状态分两类:UI 状态(弹窗开关、选中项)和服务端状态(接口数据、加载态、缓存)。后者天然带有异步、过期、重试、共享等复杂度,不该用 useState 自己硬扛。TanStack Query 专门接管这一层,你只声明“要什么数据”,它负责缓存、后台刷新、失败重试和跨组件共享。

用 useQuery 拉取并缓存数据

queryKey 是缓存的身份证,相同 key 的请求会复用同一份结果。staleTime 控制多久之内算“新鲜”,window focus 不触发刷新可以避免切回页面就闪一下。

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

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 30_000,
      retry: 2,
      refetchOnWindowFocus: false,
    },
  },
});

async function fetchUser(id: string): Promise<{ id: string; name: string }> {
  const res = await fetch(`/api/users/${id}`);
  if (!res.ok) throw new Error(`请求失败: ${res.status}`);
  return res.json();
}

function UserCard({ id }: { id: string }) {
  const { data, isLoading, isError, error } = useQuery({
    queryKey: ["user", id],
    queryFn: () => fetchUser(id),
  });

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

export function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <UserCard id="1" />
    </QueryClientProvider>
  );
}

用 useMutation 写数据并联动缓存

写操作走 useMutation。关键在于 onSuccess 里调用 invalidateQueries,让相关列表缓存失效并自动重新拉取,避免手动维护数组。

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

async function createPost(body: { title: string }) {
  const res = await fetch("/api/posts", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(body),
  });
  if (!res.ok) throw new Error("创建失败");
  return res.json();
}

function NewPostForm() {
  const qc = useQueryClient();
  const mutation = useMutation({
    mutationFn: createPost,
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["posts"] });
    },
  });

  return (
    <button onClick={() => mutation.mutate({ title: "新文章" })}>
      {mutation.isPending ? "提交中" : "发布"}
    </button>
  );
}

工程收益

  • 组件不再持有 loading/error/数据的零散 useState,逻辑收敛到 hook。
  • 相同 queryKey 的多个组件共享一份请求与缓存,天然去重。
  • retry 与 staleTime 集中配置,重试策略不再散落各处。
T

test1

文章作者

把“服务端状态”从组件里剥离出来 组件里的状态分两类:UI 状态(弹窗开关、选中项)和服务端状态(接口数据、加载态、缓...

分类
技术
发布时间
2026-09-20
字数
约 2285 字
阅读
4 次