useSWR/useSWRMutationでサーバーデータを管理します。データ取得、変更、SWRキー管理を含む、カスタムフックパターンを実装します。
重要: useSWR/useSWRMutation/hcをコンポーネント内で直接使用せず、必ずカスタムフック経由で使用します。
このスキルは以下の場合に使用してください:
注意: クライアント内で完結する UI 状態(サイドバー、テーマ、URL 同期)には manage-client-state スキルを使用してください。
// 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
// 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
})
}
// 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(一覧)[entity]-swr-keys.ts で一元管理apps/admin/src/swr/[entity]/use-mutate-[entity].ts(同一ファイル内で複数export function)useState不要、isMutatingを直接使用router.push()のみ(router.refresh()は不要)mutate()は使用しない(Background Revalidationに任せる)2つのパターンがあり、エンティティの特性に応じて使い分けます:
パターンA(一般的): 詳細ページ(/[entity]/[id])がある
entityKeys.detail(id)useUpdateEntity(id: string) - 初期化時にidを受け取るパターンB(例外): 一覧で直接CRUD操作
entityKeys.list()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 を参照してください: