| name | manage-swr-data |
| description | useSWR/useSWRMutationでサーバーデータを管理します。データ取得、変更、SWRキー管理を含む、カスタムフックパターンを実装します。 |
SWRデータ管理スキル
重要: useSWR/useSWRMutation/hcをコンポーネント内で直接使用せず、必ずカスタムフック経由で使用します。
いつ使うか
このスキルは以下の場合に使用してください:
- サーバーからデータを取得する
- サーバーのデータを作成・更新・削除する
- データ取得・変更のロジックをコンポーネントから分離したい
- キャッシュ管理を統一したい
注意: クライアント内で完結する UI 状態(サイドバー、テーマ、URL 同期)には manage-client-state スキルを使用してください。
クイックスタート
1. SWRキー定義
// apps/admin/src/swr/users/user-swr-keys.ts
import type { SearchUsersParams } from '@/features/users/lib/search-params'
export const userSwrKeys = {
list: (params: SearchUsersParams) => ['admin', 'users', params] as const,
detail: (id: string) => ['admin', 'users', id] as const,
} as const
2. データ取得フック
// apps/admin/src/swr/users/use-user.ts
import useSWR from 'swr'
import { parseResponse } from 'hono/client'
import { hc } from '@/utils/hc'
import { userSwrKeys } from './user-swr-keys'
export function useUser(id: string) {
return useSWR(userSwrKeys.detail(id), async () => {
const data = await parseResponse(
hc.admin.users[':id'].$get({ param: { id } })
)
return data.user
})
}
3. データ変更フック
// apps/admin/src/swr/users/use-mutate-user.ts
import { useRouter } from 'next/navigation'
import type { CreateUserBody } from '@repo/schemas/request/admin/users.dto'
import { parseResponse } from 'hono/client'
import { toast } from 'sonner'
import useSWRMutation from 'swr/mutation'
import { hc } from '@/utils/hc'
export function useCreateUser() {
const router = useRouter()
const { trigger, isMutating: isCreating } = useSWRMutation(
['/admin/users', 'create'],
async (_key, { arg }: { arg: CreateUserBody }) => {
return await parseResponse(hc.admin.users.$post({ json: arg }))
},
{
onSuccess: () => {
toast.success('ユーザーを作成しました')
router.push('/users')
},
onError: (e) => {
toast.error(e instanceof Error ? e.message : 'ユーザーの作成に失敗しました')
},
}
)
return { createUser: trigger, isCreating }
}
重要ルール
データ取得
- カスタムフック経由:
useSWR/hcを直接使用しない - 配置:
apps/admin/src/swr/[entity]/use-[entity].ts(単一)、use-[entities].ts(一覧) - SWRキー:
[entity]-swr-keys.tsで一元管理 - parseResponse: Hono RPCの型安全なエラーハンドリング
データ変更
- 配置:
apps/admin/src/swr/[entity]/use-mutate-[entity].ts(同一ファイル内で複数export function) - フックの使用場所: カスタムボタンコンポーネント内、またはConfirmation Dialog内
- 状態管理:
useState不要、isMutatingを直接使用 - ナビゲーション:
router.push()のみ(router.refresh()は不要) - キャッシュ無効化:
mutate()は使用しない(Background Revalidationに任せる)
Mutation パターン
2つのパターンがあり、エンティティの特性に応じて使い分けます:
パターンA(一般的): 詳細ページ(/[entity]/[id])がある
- Mutation key:
entityKeys.detail(id) - Hook定義:
useUpdateEntity(id: string)- 初期化時にidを受け取る
パターンB(例外): 一覧で直接CRUD操作
- Mutation key:
entityKeys.list() - Hook定義:
useUpdateEntity()- 実行時にidを受け取る
詳細は mutation-patterns.md を参照してください。
ディレクトリ構造
apps/admin/src/swr/
└── [entity]/
├── [entity]-swr-keys.ts # SWRキー定義
├── use-[entity].ts # 単一データ取得
├── use-[entities].ts # 一覧データ取得
└── use-mutate-[entity].ts # データ変更(複数フック定義)
詳細パターン
詳細な実装パターンについては references を参照してください:
- fetch-data.md - データ取得、エラーハンドリング、条件付きフェッチ
- mutate-data.md - データ変更、カスタムボタン、Confirmation Dialog
- mutation-patterns.md - パターンA/B、楽観的更新、キャッシュ戦略
関連スキル
- build-api-hono: Hono RPC統合、型安全なAPI呼び出し
- handle-forms-rhf-zod: フォームとの統合
- optimize-conditional-rendering-activity: データ取得状態の表示
- manage-client-state: UI状態管理との使い分け