studio-queries について
Studio のデータコードで使う React Query のパターンをまとめた開発スキルです。型付きクエリオプション、クエリキー、ミューテーションフック、コンポーネントの状態表示を扱います。
主な機能
- 01ドメイン別クエリキーの定義
- 02型付きクエリオプションの作成
- 03命令的なクエリ取得への対応
- 04キャッシュ無効化付きミューテーションフック
- 05待機・エラー・成功状態の表示
活用シーン
- 01Studio にデータクエリを追加
- 02React コンポーネント外でクエリデータを取得
- 03キャッシュ更新を伴うミューテーションを実装
- 04ロードとエラー状態を一貫して処理
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ supabase/ supabase --skill studio-queriesインストール後、Claude Code で/studio-queriesを入力して読み込まれたか確認します。
詳細
Studio のクエリとミューテーション(React Query)
apps/studio/data/ のパターンに従ってください。参考例:
- クエリオプション:
apps/studio/data/table-editor/table-editor-query.ts - ミューテーションフック:
apps/studio/data/edge-functions/edge-functions-update-mutation.ts - キー:
apps/studio/data/edge-functions/keys.ts
クエリキー
ドメインごとに keys.ts を定義してください。as const を使った配列キーで *Keys ヘルパーをエクスポートします。コンポーネント内にクエリキーを直接記述しないでください。
export const edgeFunctionsKeys = {
list: (projectRef: string | undefined) => ['projects', projectRef, 'edge-functions'] as const,
detail: (projectRef: string | undefined, slug: string | undefined) =>
['projects', projectRef, 'edge-function', slug, 'detail'] as const,
}
クエリオプション(推奨パターン)
@tanstack/react-query の queryOptions を使用してください。これにより型安全性が確保され、useQuery() と queryClient.fetchQuery() の両方で使用できます。
ルール:
XVariables、XData、XErrorの型をエクスポートします(ドメイン名を先頭に付けます)getX(variables, signal?)関数をプライベートに実装します:- 必須の変数がない場合はエラーをスローします
- キャンセルに対応するため、
signalを渡します - 失敗時は
handleError(error)を呼び出します(この関数はスローします)。成功時はdataを返します - エクスポートしないでください。命令的な取得には
queryClient.fetchQuery(xQueryOptions(...))を使用します
queryOptionsを使ってxQueryOptions()をエクスポートします- 必須の変数がそろうまでクエリが実行されないよう、
enabledで制御します - プラットフォーム専用のクエリ:
enabledにlib/constantsのIS_PLATFORMを含めます xQueryOptionsに追加のパラメーターを加えないでください。呼び出し側で分割代入を使って上書きします:{ ...xQueryOptions(vars), enabled: true }
import { queryOptions } from '@tanstack/react-query'
import { xKeys } from './keys'
import { get, handleError } from '@/data/fetchers'
import { IS_PLATFORM } from '@/lib/constants'
import { ResponseError } from '@/types'
export type XVariables = { projectRef?: string }
export type XError = ResponseError
async function getX({ projectRef }: XVariables, signal?: AbortSignal) {
if (!projectRef) throw new Error('projectRef is required')
const { data, error } = await get('/v1/projects/{ref}/x', {
params: { path: { ref: projectRef } },
signal,
})
if (error) handleError(error)
return data
}
export type XData = Awaited<ReturnType<typeof getX>>
export const xQueryOptions = ({ projectRef }: XVariables) =>
queryOptions({
queryKey: xKeys.list(projectRef),
queryFn: ({ signal }) => getX({ projectRef }, signal),
enabled: IS_PLATFORM && typeof projectRef !== 'undefined',
})
コンポーネントでのクエリオプションの使用
import { useQuery } from '@tanstack/react-query'
import { xQueryOptions } from '@/data/x/x-query'
const { data, isPending, isError } = useQuery(xQueryOptions({ projectRef: project?.ref }))
命令的な取得(React の外部またはコールバック内)
const queryClient = useQueryClient()
const { data: project } = useSelectedProjectQuery()
const handleClick = useCallback(
async (id: number) => {
const data = await queryClient.fetchQuery(xQueryOptions({ id, projectRef: project?.ref }))
// use data...
},
[project?.ref, queryClient]
)
ミューテーションフック
projectRef、識別子、payloadを含むVariables型をエクスポートします- 必須変数の検証と
handleErrorを含むupdateX(vars)関数をプライベートに実装します useXMutation()でラップします:UseMutationOptionsを受け取ります(mutationFnは除外します)onSuccessでawait Promise.all([...])を使い、list()とdetail()のキーを無効化しますonErrorが指定されていない場合は、デフォルトでtoast.error(...)を表示します
import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query'
import { toast } from 'sonner'
import { xKeys } from './keys'
type XUpdateVariables = { projectRef: string; slug: string; payload: XPayload }
export const useXUpdateMutation = ({
onSuccess,
onError,
...options
}: UseMutationOptions<XData, XError, XUpdateVariables> = {}) => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: updateX,
async onSuccess(data, variables, context) {
await Promise.all([
queryClient.invalidateQueries({
queryKey: xKeys.detail(variables.projectRef, variables.slug),
}),
queryClient.invalidateQueries({ queryKey: xKeys.list(variables.projectRef) }),
])
await onSuccess?.(data, variables, context)
},
async onError(error, variables, context) {
if (onError === undefined) toast.error(`Failed to update: ${error.message}`)
else onError(error, variables, context)
},
...options,
})
}
コンポーネントでの使用
- React Query v5 のフラグを使います:初回読み込みには
isPending、バックグラウンドでの再取得にはisFetchingを使用します - 状態は明示的に、pending → error → success の順にレンダリングします
コメント
Markdown 対応