General
PromptBeginner5 minmarkdown
Untitled Skill
193
React Query conventions for data fetching in Supabase Studio. Use when
Loading actions...
Main instructions and any bundled files for this skill.
Follow the patterns in apps/studio/data/. Reference examples:
apps/studio/data/table-editor/table-editor-query.tsapps/studio/data/edge-functions/edge-functions-update-mutation.tsapps/studio/data/edge-functions/keys.tsDefine a keys.ts per domain. Export *Keys helpers using array keys with as const. Never inline query keys in components.
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,
}
Use queryOptions from @tanstack/react-query. This gives type safety and works with both useQuery() and queryClient.fetchQuery().
Rules:
XVariables, XData, and XError types (prefixed with the domain name)getX(variables, signal?) function:
signal for cancellationhandleError(error) on failure (which throws); returns data on successqueryClient.fetchQuery(xQueryOptions(...)) for imperative fetchingxQueryOptions() using queryOptionsenabled so the query doesn't run until required variables existIS_PLATFORM from lib/constants in enabledxQueryOptions — callers override by destructuring: { ...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 }))
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]
)
Variables type with projectRef, identifiers, and payloadupdateX(vars) function with required variable validation and handleErroruseXMutation():
UseMutationOptions (omit mutationFn)list() + detail() keys in onSuccess with await Promise.all([...])toast.error(...) when onError isn't providedimport { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query'
import toast from 'react-hot-toast'
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,
})
}
isPending for initial load, isFetching for background refetchesTypeScript and ESLint rules that MUST be followed when creating, modifying, or reviewing any file under apps/frontend/, including .ts, .tsx, .js, and .jsx files. Also apply when discussing frontend li...
risks