关于 graphql-schema
面向使用 GraphQL 与 Apollo 的开发者,提供从 .gql 文件定义查询和变更到生成类型化 hooks 的实现规范。内容还涵盖变更错误处理、加载反馈、缓存策略和评分更新。
主要功能
- 01将查询与变更写入 .gql 文件
- 02通过代码生成类型和 hooks
- 03为变更处理错误与状态反馈
- 04介绍缓存策略和评分更新
适用场景
- 01实现类型化 GraphQL 查询
- 02构建带状态反馈的变更表单
- 03复用字段片段并配置缓存
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ chriswiles/ claude-code-showcase --skill graphql-schema安装后在 Claude Code 中输入/graphql-schema确认已加载。
详细介绍
GraphQL Schema 模式
核心规则
- 绝不内联
gql字面量——创建.gql文件 - 创建或修改
.gql文件后,务必运行代码生成 - 务必为变更添加
onError处理程序 - 使用生成的 hooks——绝不编写原始 Apollo hooks
文件结构
src/
├── components/
│ └── ItemList/
│ ├── ItemList.tsx
│ ├── GetItems.gql # Query definition
│ └── GetItems.generated.ts # Auto-generated (don't edit)
└── graphql/
└── mutations/
└── CreateItem.gql # Shared mutations
创建查询
步骤 1:创建 .gql 文件
# src/components/ItemList/GetItems.gql
query GetItems($limit: Int, $offset: Int) {
items(limit: $limit, offset: $offset) {
id
name
description
createdAt
}
}
步骤 2:运行代码生成
npm run gql:typegen
步骤 3:导入并使用生成的 hook
import { useGetItemsQuery } from './GetItems.generated';
const ItemList = () => {
const { data, loading, error, refetch } = useGetItemsQuery({
variables: { limit: 20, offset: 0 },
});
if (error) return <ErrorState error={error} onRetry={refetch} />;
if (loading && !data) return <LoadingSkeleton />;
if (!data?.items.length) return <EmptyState />;
return <List items={data.items} />;
};
创建变更
步骤 1:创建 .gql 文件
# src/graphql/mutations/CreateItem.gql
mutation CreateItem($input: CreateItemInput!) {
createItem(input: $input) {
id
name
description
}
}
步骤 2:运行代码生成
npm run gql:typegen
步骤 3:使用时务必进行错误处理
import { useCreateItemMutation } from 'graphql/mutations/CreateItem.generated';
const CreateItemForm = () => {
const [createItem, { loading }] = useCreateItemMutation({
// Success handling
onCompleted: (data) => {
toast.success({ title: 'Item created' });
navigation.goBack();
},
// ERROR HANDLING IS REQUIRED
onError: (error) => {
console.error('createItem failed:', error);
toast.error({ title: 'Failed to create item' });
},
// Cache update
update: (cache, { data }) => {
if (data?.createItem) {
cache.modify({
fields: {
items: (existing = []) => [...existing, data.createItem],
},
});
}
},
});
return (
<Button
onPress={() => createItem({ variables: { input: formValues } })}
isDisabled={!isValid || loading}
isLoading={loading}
>
Create
</Button>
);
};
变更的 UI 要求
重要:每个变更触发器都必须:
- 在变更期间处于禁用状态——防止重复点击
- 显示加载状态——提供视觉反馈
- 包含 onError 处理程序——让用户知道操作失败
- 显示成功反馈——让用户知道操作成功
// CORRECT - Complete mutation pattern
const [submit, { loading }] = useSubmitMutation({
onError: (error) => {
console.error('submit failed:', error);
toast.error({ title: 'Save failed' });
},
onCompleted: () => {
toast.success({ title: 'Saved' });
},
});
<Button
onPress={handleSubmit}
isDisabled={!isValid || loading}
isLoading={loading}
>
Submit
</Button>
查询选项
获取策略
| 策略 | 使用时机 |
|---|---|
cache-first | 数据很少变化时 |
cache-and-network | 需要快速获取并保持数据新鲜时(默认) |
network-only | 始终需要最新数据时 |
no-cache | 从不缓存时(少见) |
常用选项
useGetItemsQuery({
variables: { id: itemId },
// Fetch strategy
fetchPolicy: 'cache-and-network',
// Re-render on network status changes
notifyOnNetworkStatusChange: true,
// Skip if condition not met
skip: !itemId,
// Poll for updates
pollInterval: 30000,
});
乐观更新
用于提供即时 UI 反馈:
const [toggleFavorite] = useToggleFavoriteMutation({
optimisticResponse: {
toggleFavorite: {
__typename: 'Item',
id: itemId,
isFavorite: !currentState,
},
},
onError: (error) => {
// Rollback happens automatically
console.error('toggleFavorite failed:', error);
toast.error({ title: 'Failed to update' });
},
});
不应使用乐观更新的情况
- 可能验证失败的操作
- 包含服务器生成值的操作
- 破坏性操作(删除)
- 影响其他用户的操作
片段
用于复用字段选择:
# src/graphql/fragments/ItemFields.gql
fragment ItemFields on Item {
id
name
description
createdAt
updatedAt
}
在查询中使用:
query GetItems {
items {
...ItemFields
}
}
反模式
// WRONG - Inline gql
const GET_ITEMS = gql`
query GetItems { items { id } }
`;
// CORRECT - Use .gql file + generated hook
import { useGetItemsQuery } from './GetItems.generated';
// WRONG - No error handler
const [mutate] = useMutation(MUTATION);
// CORRECT - Always handle errors
const [mutate] = useMutation(MUTATION, {
onError: (error) => {
console.error('mutation failed:', error);
toast.error({ title: 'Operation failed' });
},
});
// WRONG - Button not disabled during mutation
<Button onPress={submit}>Submit</Button>
// CORRECT - Disabled and loading
<Button onPress={submit} isDisabled={loading} isLoading={loading}>
Submit
</Button>
代码生成命令
# Generate types from .gql files
npm run gql:typegen
# Download schema + generate types
npm run sync-types
与其他技能的集成
- react-ui-patterns:查询的加载、错误和空状态
- testing-patterns:在测试中模拟生成的 hooks
- formik-patterns:变更提交模式
评论
支持 Markdown