# createQueryKeys

Build the React Query keys the hooks use, typed by your API, for invalidation, prefetching and optimistic updates.

## Import

```ts
import { createProxyQueryKeys, createQueryKeys } from "@noverax/courier-react"
```

## Signature

`createQueryKeys` takes the API definition, as `createQueryCaller` does; `createProxyQueryKeys` takes the API's routes, as `createProxyQueryCaller` does. Both return a key factory that builds the keys the hooks of the matching caller use:

```ts
import type { CourierRoutes, DefinedApi, RoutedApi, RouteShape } from "@noverax/courier/define"
import type { QueryKeyFactory } from "@noverax/courier-react"

declare function createQueryKeys<TApi extends DefinedApi>(api: TApi): QueryKeyFactory<TApi>

declare function createProxyQueryKeys<
  TApi extends DefinedApi,
  TEndpoints extends Readonly<Record<string, RouteShape>>,
>(routes: CourierRoutes<TApi, TEndpoints>): QueryKeyFactory<RoutedApi<TApi, TEndpoints>>
```

## Keys

A key is `[source, group, method?, variables?]`. The group and the method are checked against the API, so a key cannot name an endpoint that does not exist. A group inside another is named by its path, and keyed one element per group:

```ts title="lib/query.ts"
import { createQueryCaller, createQueryKeys } from "@noverax/courier-react"
import { api } from "@/api"

export const q = createQueryCaller(api)
export const queryKeys = createQueryKeys(api)

queryKeys("users")                        // ["api", "users"]
queryKeys("users", "getAll")              // ["api", "users", "getAll"]
queryKeys("users", "getById", { id: 1 })  // ["api", "users", "getById", { id: 1 }]
queryKeys("billing.invoices", "list")     // ["api", "billing", "invoices", "list"]
```

`source` is the name the caller was made for: for `createQueryKeys(api)`, the API's own name — its `defineApi({ name })`, or else the first label of its `baseURL` host — and for `createProxyQueryKeys(apiRoutes)`, the source the routes name. Build the keys for the same source as the caller, and a key names what the caller's hooks cached. A proxy caller's keys name the endpoints its routes name alone:

```ts title="lib/proxy-query.ts"
import { createProxyQueryCaller, createProxyQueryKeys } from "@noverax/courier-react"
import { apiRoutes } from "@/courier.routes"

export const q = createProxyQueryCaller(apiRoutes)
export const queryKeys = createProxyQueryKeys(apiRoutes)
```

## Invalidating

A shorter key matches every longer one under it, so the three lengths invalidate an endpoint's call with those variables, every call of an endpoint, or every endpoint of a group — and `queryKeys("billing")` every endpoint of the groups inside `billing` as well:

```ts title="components/create-user.tsx"
"use client"

import { useQueryClient } from "@noverax/courier-react"
import { q, queryKeys } from "@/lib/query"

export function CreateUser() {
  const queryClient = useQueryClient()
  const { mutate } = q.users.useMutation("create", {
    onSuccess: () => queryClient.invalidateQueries({ queryKey: queryKeys("users", "getAll") }),
  })

  return <button onClick={() => mutate({ name: "Ada" })}>Add user</button>
}
```

An infinite query's key ends with `"infinite"`, after its first page's variables; the method's key invalidates it too.

## Related

- [`createQueryCaller`](/docs/api/create-query-caller) — the direct-mode caller whose keys these are
- [`createProxyQueryCaller`](/docs/api/create-proxy-query-caller) — the proxy-mode caller
- [useQuery](/docs/react-query/use-query#auto-generated-query-keys) — how the hooks build their keys
