关于 studio-queries
一项介绍 Studio 数据代码中 React Query 模式的开发技能,涵盖类型化查询选项、查询键、变更钩子和组件加载状态。
主要功能
- 01定义领域专属查询键
- 02创建类型化查询选项
- 03支持命令式查询数据获取
- 04构建带缓存失效的变更钩子
- 05统一呈现等待、错误和成功状态
适用场景
- 01为 Studio 添加数据查询
- 02在 React 组件外获取查询数据
- 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类型 - 实现一个私有的
updateX(vars)函数,进行必需变量校验并调用handleError - 将其封装在
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 - 按顺序明确渲染各状态:待处理 → 错误 → 成功
评论
支持 Markdown