# graphql-schema
> GraphQL 查询、Mutation 与代码生成模式;在创建 GraphQL 操作、使用 Apollo Client 或生成类型时使用。
- Author: ZoneCNH
- Repository: OpsFlux/claude-code-showcase
- Version: 20260108185000
- Stars: 0
- Forks: 0
- Last Updated: 2026-02-07
- Source: https://github.com/OpsFlux/claude-code-showcase
- Web: https://mule.run/skillshub/@@OpsFlux/claude-code-showcase~graphql-schema:20260108185000
---
---
name: graphql-schema
description: GraphQL 查询、Mutation 与代码生成模式;在创建 GraphQL 操作、使用 Apollo Client 或生成类型时使用。
---
# GraphQL Schema 模式
## 核心规则
1. **绝不要内联 `gql` 字面量**——创建独立 `.gql` 文件
2. **每次修改 `.gql` 后都要运行 codegen**
3. **所有 Mutation 必须提供 `onError`**
4. **只使用生成的 Hook**——不要直接写 Apollo 原生 Hook
## 文件结构
```
src/
├── components/
│ └── ItemList/
│ ├── ItemList.tsx
│ ├── GetItems.gql # 查询定义
│ └── GetItems.generated.ts # 自动生成(勿改)
└── graphql/
└── mutations/
└── CreateItem.gql # 共享 Mutation
```
## 创建查询
### 第一步:编写 .gql
```graphql
# src/components/ItemList/GetItems.gql
query GetItems($limit: Int, $offset: Int) {
items(limit: $limit, offset: $offset) {
id
name
description
createdAt
}
}
```
### 第二步:运行 codegen
```bash
npm run gql:typegen
```
### 第三步:导入并使用生成的 Hook
```typescript
import { useGetItemsQuery } from './GetItems.generated';
const ItemList = () => {
const { data, loading, error, refetch } = useGetItemsQuery({
variables: { limit: 20, offset: 0 },
});
if (error) return ;
if (loading && !data) return ;
if (!data?.items.length) return ;
return
;
};
```
## 创建 Mutation
### 第一步:编写 .gql
```graphql
# src/graphql/mutations/CreateItem.gql
mutation CreateItem($input: CreateItemInput!) {
createItem(input: $input) {
id
name
description
}
}
```
### 第二步:运行 codegen
```bash
npm run gql:typegen
```
### 第三步:强制加入错误处理
```typescript
import { useCreateItemMutation } from 'graphql/mutations/CreateItem.generated';
const CreateItemForm = () => {
const [createItem, { loading }] = useCreateItemMutation({
// 成功处理
onCompleted: (data) => {
toast.success({ title: 'Item created' });
navigation.goBack();
},
// 必填:错误处理
onError: (error) => {
console.error('createItem failed:', error);
toast.error({ title: 'Failed to create item' });
},
// 缓存更新
update: (cache, { data }) => {
if (data?.createItem) {
cache.modify({
fields: {
items: (existing = []) => [...existing, data.createItem],
},
});
}
},
});
return (
);
};
```
## Mutation UI 要求
**关键:触发 Mutation 的控件必须满足:**
1. **执行过程中禁用**——防止重复点击
2. **展示加载状态**——提供视觉反馈
3. **具备 onError**——失败时提示用户
4. **成功反馈**——让用户知道操作完成
```typescript
// 正确:完整 Mutation 模式
const [submit, { loading }] = useSubmitMutation({
onError: (error) => {
console.error('submit failed:', error);
toast.error({ title: 'Save failed' });
},
onCompleted: () => {
toast.success({ title: 'Saved' });
},
});
```
## 查询选项
### Fetch Policy
| 策略 | 适用场景 |
|------|----------|
| `cache-first` | 数据很少变化 |
| `cache-and-network` | 需要速度也需要最新(默认) |
| `network-only` | 必须拿最新数据 |
| `no-cache` | 不缓存(极少) |
### 常用配置
```typescript
useGetItemsQuery({
variables: { id: itemId },
// 拉取策略
fetchPolicy: 'cache-and-network',
// 网络状态变化时重新渲染
notifyOnNetworkStatusChange: true,
// 条件不满足时跳过
skip: !itemId,
// 轮询更新
pollInterval: 30000,
});
```
## 乐观更新
用于即时 UI 反馈:
```typescript
const [toggleFavorite] = useToggleFavoriteMutation({
optimisticResponse: {
toggleFavorite: {
__typename: 'Item',
id: itemId,
isFavorite: !currentState,
},
},
onError: (error) => {
// 回滚自动发生
console.error('toggleFavorite failed:', error);
toast.error({ title: 'Failed to update' });
},
});
```
### 何时不要使用乐观更新
- 可能因校验失败的操作
- 依赖服务端生成值
- 破坏性操作(删除)
- 会影响其他用户的操作
## 片段(Fragments)
```graphql
# src/graphql/fragments/ItemFields.gql
fragment ItemFields on Item {
id
name
description
createdAt
updatedAt
}
```
在查询中使用:
```graphql
query GetItems {
items {
...ItemFields
}
}
```
## 反模式
```typescript
// 错误:内联 gql
const GET_ITEMS = gql`
query GetItems { items { id } }
`;
// 正确:.gql + 生成的 Hook
import { useGetItemsQuery } from './GetItems.generated';
// 错误:缺少错误处理
const [mutate] = useMutation(MUTATION);
// 正确:始终处理错误
const [mutate] = useMutation(MUTATION, {
onError: (error) => {
console.error('mutation failed:', error);
toast.error({ title: 'Operation failed' });
},
});
// 错误:Mutation 期间按钮未禁用
// 正确:禁用并显示加载
```
## Codegen 命令
```bash
# 从 .gql 生成类型
npm run gql:typegen
# 下载 schema 并生成类型
npm run sync-types
```
## 与其他技能协作
- **react-ui-patterns**:查询的加载/错误/空态
- **testing-patterns**:在测试中 mock 生成的 Hook
- **formik-patterns**:Mutation 表单提交流程