Recipes
Use with TanStack Query
Use this when your app uses TanStack Query for caching, refetching and loading states, and liaise for the calls. The two disagree on one thing. liaise never throws, and TanStack Query treats a query as failed only when its query function throws or returns a rejected promise.
A small unwrap function converts at that one boundary. api is the client from Quick start.
import type { Result } from 'liaise'
// TanStack Query expects a failed query to throw. Do it here, at your edge.
async function unwrap<T>(call: Promise<Result<T>>): Promise<T> {
const { data, error } = await call
if (error) throw error
return data
}
export const userQuery = (id: string) => ({
queryKey: ['user', id],
// TanStack's signal cancels the request when the query is no longer needed.
queryFn: ({ signal }: { signal: AbortSignal }) => unwrap(api.getUser({ id }, { signal })),
})
// React: useQuery(userQuery(id))
// Vue: useQuery(computed(() => userQuery(id.value)))
// Svelte: createQuery(() => userQuery(id))
// Solid: useQuery(() => userQuery(id()))
Why it works
unwrapreturnsdataon success and throws theApiErroron failure. TanStack sees a failed query, and keeps theApiErrorin the query’serror.- TanStack’s signal cancels the call. TanStack Query gives every query function an
AbortSignal, and aborts it when the query becomes out of date or inactive. Passing it on toapi.getUsercancels the request at that moment (Query cancellation). - One options object works with every TanStack adapter. The comments show the call in React, Vue, Svelte and Solid. The test doesn’t run those lines.
Typing the error
error is the ApiError liaise returned. It isn’t an Error subclass, so it has no message: read error.kind and error.status (ApiError). To type it in every query, register ApiError as TanStack’s defaultError:
import '@tanstack/react-query'
import type { ApiError } from 'liaise'
declare module '@tanstack/react-query' {
interface Register {
defaultError: ApiError
}
}
That is the React adapter. The others take the same declaration under their own package name, such as @tanstack/vue-query (TanStack’s TypeScript guide).
Retrying in one place
TanStack Query retries a failed query three times by default in the browser, with exponential backoff, and 0 times on the server (Important defaults, Query retries). If your liaise client also has retryMiddleware, each of TanStack’s attempts runs liaise’s retries too. Pick one: turn off TanStack’s retry option, or leave retryMiddleware off the client these queries use.
Next: Use with React loads data in a plain useEffect, without a query library.