SKILL.md
readonly只读
name
apollo-client
description
使用 Apollo Client 4.x 构建 React 应用的指南。在以下场景使用此技能: (1) 在 React 项目中设置 Apollo Client, (2) 使用 Hooks 编写 GraphQL 查询或变更, (3) 配置缓存或缓存策略, (4) 使用响应式变量管理本地状态, (5) 排查 Apollo Client 错误或性能问题。
Apollo Client 4.x 指南
Apollo Client 是一个全面的 JavaScript 状态管理库,可让您通过 GraphQL 管理本地和远程数据。4.x 版本带来了改进的缓存、更好的 TypeScript 支持以及 React 19 兼容性。
集成指南
选择与您的应用设置匹配的集成指南:
- 客户端应用 - 适用于无 SSR 的客户端 React 应用(Vite、Create React App 等)
- Next.js App Router - 适用于使用 App Router 和 React Server Components 的 Next.js 应用
- React Router 框架模式 - 适用于支持流式 SSR 的 React Router 7 应用
- TanStack Start - 适用于使用现代路由的 TanStack Start 应用
每个指南都包含安装步骤、配置以及针对该环境优化的框架特定模式。
快速参考
基本查询
import { gql } from "@apollo/client";
import { useQuery } from "@apollo/client/react";
const GET_USER = gql`
query GetUser($id: ID!) {
user(id: $id) {
id
name
}
}
`;
function UserProfile({ userId }: { userId: string }) {
const { loading, error, data, dataState } = useQuery(GET_USER, {
variables: { id: userId },
});
if (loading) return <p>加载中...</p>;
if (error) return <p>错误: {error.message}</p>;
// TypeScript 提示:为了更严格的类型收窄,您也可以在访问 data 之前检查 `dataState === "complete"`
return <div>{data?.user.name}</div>;
}
基本变更
import { gql } from "@apollo/client";
import { useMutation } from "@apollo/client/react";
const CREATE_USER = gql`
mutation CreateUser($input: CreateUserInput!) {
createUser(input: $input) {
id
name
}
}
`;
function CreateUserForm() {
const [createUser, { loading, error }] = useMutation(CREATE_USER);
const handleSubmit = async (name: string) => {
await createUser({ variables: { input: { name } } });
};
return <button onClick={() => handleSubmit("John")}>创建用户</button>;
}
Suspense 查询
import { Suspense } from "react";
import { useSuspenseQuery } from "@apollo/client/react";
function UserProfile({ userId }: { userId: string }) {
const { data } = useSuspenseQuery(GET_USER, {
variables: { id: userId },
});
return <div>{data.user.name}</div>;
}
function App() {
return (
<Suspense fallback={<p>正在加载用户...</p>}>
<UserProfile userId="1" />
</Suspense>
);
}
参考文件
特定主题的详细文档:
- TypeScript 代码生成 - GraphQL Code Generator 设置,用于类型安全操作
- 查询 - useQuery、useLazyQuery、轮询、重新获取
- Suspense Hooks - useSuspenseQuery、useBackgroundQuery、useReadQuery、useLoadableQuery
- 变更 - useMutation、乐观 UI、缓存更新
- 片段 - 片段共置、useFragment、useSuspenseFragment、数据掩码
- 缓存 - InMemoryCache、typePolicies、缓存操作
- 状态管理 - 响应式变量、本地状态
- 错误处理 - 错误策略、错误链接、重试
- 故障排除 - 常见问题及解决方案
关键规则
查询最佳实践
- 每个页面通常应只有一个查询,由共置的片段组成。 在所有非页面组件中使用
useFragment或useSuspenseFragment。使用@defer允许折叠下方的慢字段稍后流式加载,避免阻塞页面加载。 - 片段用于共置,而非复用。 每个片段应精确描述特定组件的数据需求,不应为了公共字段而在组件间共享。有关片段共置和数据掩码的详细信息,请参阅片段参考。
- 使用非 Suspense Hooks(
useQuery、useLazyQuery)时,始终在 UI 中处理loading和error状态。使用 Suspense Hooks(useSuspenseQuery、useBackgroundQuery)时,React 通过<Suspense>边界和错误边界处理这些状态。 - 使用
fetchPolicy控制每个查询的缓存行为 - 使用 TypeScript 类型服务器查找函数和选项的文档(Apollo Client 有广泛的文档注释)
变更最佳实践
- 如果 schema 允许,变更返回值应返回更新缓存所需的所有内容。 不应需要手动更新或重新获取。
- 如果变更响应不足,请仔细权衡手动缓存操作与重新获取。手动更新可能遗漏服务器逻辑。如果需要,考虑乐观更新并配合细粒度的重新获取。
- 在 UI 中优雅地处理错误
- 谨慎使用
refetchQueries(优先让缓存自动更新)
缓存最佳实践
- 为没有
id字段的类型配置keyFields - 对于不包含标识符且旨在将相关字段分组到父级下的类型,通过设置
keyFields: false禁用规范化 - 使用
typePolicies处理分页和计算字段 - 理解缓存规范化以调试问题
- 对所有新应用启用数据掩码 - 它防止组件访问它们不拥有的片段数据,强制执行适当的数据边界并防止过度渲染
性能
- 通过适当的字段选择避免过度获取
- 根据用例配置适当的
fetchPolicy - 使用
@defer实现延迟查询部分的增量交付,使用@stream实现列表字段的流式传输(@stream在 Apollo Client 4.1+ 中可用) - 在现代应用中优先使用 Suspense Hooks(
useSuspenseQuery、useBackgroundQuery) 以获得更好的加载状态处理和代码简洁性
基本规则
- 始终使用 Apollo Client 4.x 模式(而非 v3 或更早版本)
- 始终使用
ApolloProvider包裹您的应用 - 使用非 Suspense Hooks 时始终处理加载和错误状态
- 在现代应用中优先使用 Suspense Hooks(
useSuspenseQuery、useBackgroundQuery)以获得更好的开发体验 - 切勿将 Apollo Client 存储在 React 状态中(使用模块级或上下文)
- 对于读取密集型数据优先使用
cache-first,对于实时数据优先使用network-only - 使用 TypeScript 以获得更好的 GraphQL 类型安全性
- 实现适当的缓存更新,而不是重新获取整个查询
- 在协作调试 Apollo Client 问题时,建议人类查看 Apollo DevTools






