### Install Query Key Factory Source: https://github.com/lukemorales/query-key-factory/blob/main/README.md Install the Query Key Factory package using npm. ```Shell npm install @lukemorales/query-key-factory ``` -------------------------------- ### Define and Merge Query Keys with Factory Source: https://github.com/lukemorales/query-key-factory/blob/main/README.md This snippet demonstrates how to define query keys for different features (users, todos) using `createQueryKeys` and then combine them into a single object using `mergeQueryKeys`. It shows examples of simple keys, keys with parameters, and keys with associated query functions and contextual queries. ```TypeScript import { createQueryKeys, mergeQueryKeys } from "@lukemorales/query-key-factory"; // queries/users.ts export const users = createQueryKeys('users', { all: null, detail: (userId: string) => ({ queryKey: [userId], queryFn: () => api.getUser(userId), }), }); // queries/todos.ts export const todos = createQueryKeys('todos', { detail: (todoId: string) => [todoId], list: (filters: TodoFilters) => ({ queryKey: [{ filters }], queryFn: (ctx) => api.getTodos({ filters, page: ctx.pageParam }), contextQueries: { search: (query: string, limit = 15) => ({ queryKey: [query, limit], queryFn: (ctx) => api.getSearchTodos({ page: ctx.pageParam, filters, limit, query, }), }), }, }), }); // queries/index.ts export const queries = mergeQueryKeys(users, todos); ``` -------------------------------- ### Advanced React Query Usage with Factory Keys Source: https://github.com/lukemorales/query-key-factory/blob/main/README.md This snippet provides more advanced examples of using factory-generated keys with React Query. It includes using keys with parameters and filters (`queries.todos.list`), accessing contextual queries (`queries.todos.list(filters)._ctx.search`), and using keys for cache updates and invalidation within a `useMutation` hook. ```TypeScript import { queries } from '../queries'; export function useTodos(filters: TodoFilters) { return useQuery(queries.todos.list(filters)); }; export function useSearchTodos(filters: TodoFilters, query: string, limit = 15) { return useQuery({ ...queries.todos.list(filters)._ctx.search(query, limit), enabled: Boolean(query), }); }; export function useUpdateTodo() { const queryClient = useQueryClient(); return useMutation(updateTodo, { onSuccess(newTodo) { queryClient.setQueryData(queries.todos.detail(newTodo.id).queryKey, newTodo); // invalidate all the list queries queryClient.invalidateQueries({ queryKey: queries.todos.list._def, refetchActive: false, }); }, }); }; ``` -------------------------------- ### Use Merged Query Keys in Basic React Query Hooks Source: https://github.com/lukemorales/query-key-factory/blob/main/README.md This example shows how to consume the merged query keys object (`queries`) within React Query's `useQuery` hook. It illustrates using a simple key (`queries.users.all`) and a key with a parameter (`queries.users.detail(id)`). ```TypeScript import { queries } from '../queries'; export function useUsers() { return useQuery({ ...queries.users.all, queryFn: () => api.getUsers(), }); }; export function useUserDetail(id: string) { return useQuery(queries.users.detail(id)); }; ``` -------------------------------- ### Using Generated Query Options with React Query (TSX) Source: https://github.com/lukemorales/query-key-factory/blob/main/CHANGELOG.md Provides examples of integrating the query options objects generated by query-key-factory with the useQuery hook from React Query. It shows how to directly pass the object, spread it to add additional options like enabled, and access nested context queries via the _ctx property. ```TSX export const Person = ({ id }) => { const personQuery = useQuery(people.person(id)); return { /* render person data */ }; }; export const Ships = ({ personId }) => { const shipsQuery = useQuery({ ...people.person(personId)._ctx.ships, enabled: !!personId, }); return { /* render ships data */ }; }; export const Film = ({ id, personId }) => { const filmQuery = useQuery(people.person(personId)._ctx.film(id)); return { /* render film data */ }; }; ``` -------------------------------- ### Output Structure of Generated Query Options Object (Text) Source: https://github.com/lukemorales/query-key-factory/blob/main/CHANGELOG.md Illustrates the structure of the object returned when calling a query key factory function like people.person("person_01"). It shows the combined queryKey, the associated queryFn, and the _ctx property containing context queries. ```Text // => output: // { // queryKey: ['people', 'person', 'person_01'], // queryFn: () => api.getPerson({ params: { id: 'person_01' } }), // _ctx: { ...queries declared inside "contextQueries" } // } ``` -------------------------------- ### Define and Use Contextual Queries Source: https://github.com/lukemorales/query-key-factory/blob/main/README.md Explains how to define nested, context-dependent queries using the `contextQueries` property. It shows how these queries are nested under a `_ctx` property in the output and how to access and use them in a `useQuery` hook. ```TypeScript export const users = createQueryKeys('users', { detail: (userId: string) => ({ queryKey: [userId], queryFn: () => api.getUser(userId), contextQueries: { likes: { queryKey: null, queryFn: () => api.getUserLikes(userId), }, }, }), }); // => createQueryKeys output: // { // _def: ['users'], // detail: (userId: string) => { // queryKey: ['users', 'detail', userId], // queryFn: (ctx: QueryFunctionContext) => api.getUser(userId), // _ctx: { // likes: { // queryKey: ['users', 'detail', userId, 'likes'], // queryFn: (ctx: QueryFunctionContext) => api.getUserLikes(userId), // }, // }, // }, // } export function useUserLikes(userId: string) { return useQuery(users.detail(userId)._ctx.likes); }; ``` -------------------------------- ### Generate Query Options with Key and Function Source: https://github.com/lukemorales/query-key-factory/blob/main/README.md Shows how to define both the `queryKey` and `queryFn` together within the `createQueryKeys` definition. This allows the factory to generate a complete query options object that can be directly passed to `useQuery`. ```TypeScript export const users = createQueryKeys('users', { detail: (userId: string) => ({ queryKey: [userId], queryFn: () => api.getUser(userId), }), }); // => createQueryKeys output: // { // _def: ['users'], // detail: (userId: string) => { // queryKey: ['users', 'detail', userId], // queryFn: (ctx: QueryFunctionContext) => api.getUser(userId), // }, // } export function useUserDetail(id: string) { return useQuery(users.detail(id)); }; ``` -------------------------------- ### Adapting useQuery Calls to New Object Output (Diff) Source: https://github.com/lukemorales/query-key-factory/blob/main/CHANGELOG.md Compares the old and new ways of using the generated query keys/options with useQuery. It shows that you now access the queryKey property explicitly or, preferably, pass the entire generated options object directly to useQuery for better integration with React Query v5. ```Diff export const todosKeys = createQueryKeys('todos', { todo: (todoId: string) => [todoId], list: (filters: TodoFilters) => { queryKey: [{ filters }], queryFn: () => fetchTodosList(filters), }, }); - useQuery(todosKeys.todo(todoId), fetchTodo); + useQuery(todosKeys.todo(todoId).queryKey, fetchTodo); - useQuery(todosKeys.list(filters), fetchTodosList); + useQuery(todosKeys.list(filters).queryKey, todosKeys.list(filters).queryFn); // even better refactor, preparing for React Query v5 + useQuery({ + ...todosKeys.todo(todoId), + queryFn: fetchTodo, + }); + useQuery(todosKeys.list(filters)); ``` -------------------------------- ### Standard Query Key Output Structure Source: https://github.com/lukemorales/query-key-factory/blob/main/README.md Illustrates the standard output structure generated by `createQueryKeys` for keys defined with parameters or serializable objects. It shows how the base scope and key parts are combined into the final `queryKey` array. ```TypeScript export const todos = createQueryKeys('todos', { detail: (todoId: string) => [todoId], list: (filters: TodoFilters) => ({ queryKey: [{ filters }], }), }); // => createQueryKeys output: // { // _def: ['todos'], // detail: (todoId: string) => { // queryKey: ['todos', 'detail', todoId], // }, // list: (filters: TodoFilters) => { // queryKey: ['todos', 'list', { filters }], // }, // } ``` -------------------------------- ### Using Objects for Query Options Declaration (Diff) Source: https://github.com/lukemorales/query-key-factory/blob/main/CHANGELOG.md Demonstrates the change where a plain object returned by a factory function is now interpreted as query options (like queryKey, queryFn). If you intend to compose the query key with an object, it must be placed inside the queryKey array property within the options object. ```Diff export const todosKeys = createQueryKeys('todos', { - list: (filters: TodoFilters) => ({ filters }), + list: (filters: TodoFilters) => ({ + queryKey: [{ filters }], + }), }); ``` -------------------------------- ### Standardizing Dynamic Query Key Values to Arrays (Diff) Source: https://github.com/lukemorales/query-key-factory/blob/main/CHANGELOG.md Shows the change required to standardize query key values. Previously, dynamic values could be plain strings or objects; now, they must be explicitly wrapped in an array, even if it's a single value or an object used for composition. ```Diff export const todosKeys = createQueryKeys('todos', { mine: null, - all: 'all-todos', + all: ['all-todos'], - list: (filters: TodoFilters) => ({ filters }), + list: (filters: TodoFilters) => [{ filters }], - todo: (todoId: string) => todoId, + todo: (todoId: string) => [todoId], }); ``` -------------------------------- ### Declaring Query Keys in a Single Store (TypeScript) Source: https://github.com/lukemorales/query-key-factory/blob/main/README.md Demonstrates using `createQueryKeyStore` to consolidate all application query keys into a single object. It defines nested keys for 'users' and 'todos', including parameterized keys with `queryKey` and `queryFn`. ```typescript export const queries = createQueryKeyStore({ users: { all: null, detail: (userId: string) => ({ queryKey: [userId], queryFn: () => api.getUser(userId), }), }, todos: { detail: (todoId: string) => [todoId], list: (filters: TodoFilters) => ({ queryKey: [{ filters }], queryFn: (ctx) => api.getTodos({ filters, page: ctx.pageParam }), }), }, }); ``` -------------------------------- ### Defining Query Keys with Nested Context Queries (TypeScript) Source: https://github.com/lukemorales/query-key-factory/blob/main/CHANGELOG.md Shows how to use createQueryKeys to define a factory for 'people' queries. It includes a dynamic 'person' key with an ID parameter, which in turn defines nested 'ships' and 'film' context queries using the contextQueries property. Each entry returns an object containing queryKey, queryFn, and _ctx for nested queries. ```TypeScript const people = createQueryKeys("people", { person: (id: number) => ({ queryKey: [id], queryFn: () => api.getPerson({ params: { id } }), contextQueries: { ships: { queryKey: null, queryFn: () => api.getShipsByPerson({ params: { personId: id }, }), }, film: (filmId: string) => ({ queryKey: [filmId], queryFn: () => api.getFilm({ params: { id: filmId }, }), }), }, }), }); ``` -------------------------------- ### Declare Query Key Store in TypeScript Source: https://github.com/lukemorales/query-key-factory/blob/main/README.md Define your application's query keys in a single file using `createQueryKeyStore` for typesafe management and auto-completion. ```TypeScript import { createQueryKeyStore } from "@lukemorales/query-key-factory"; // if you prefer to declare everything in one file export const queries = createQueryKeyStore({ users: { all: null, detail: (userId: string) => ({ queryKey: [userId], queryFn: () => api.getUser(userId), }), }, todos: { detail: (todoId: string) => [todoId], list: (filters: TodoFilters) => ({ queryKey: [{ filters }], queryFn: (ctx) => api.getTodos({ filters, page: ctx.pageParam }), contextQueries: { search: (query: string, limit = 15) => ({ queryKey: [query, limit], queryFn: (ctx) => api.getSearchTodos({ page: ctx.pageParam, filters, limit, query, }), }), }, }), }, }); ``` -------------------------------- ### Declaring and Merging Feature-Based Query Keys (TypeScript) Source: https://github.com/lukemorales/query-key-factory/blob/main/README.md Illustrates organizing query keys by feature into separate files using `createQueryKeys` and then combining them into a single `queries` object using `mergeQueryKeys`. This promotes modularity and maintainability. ```typescript // queries/users.ts export const users = createQueryKeys('users', { all: null, detail: (userId: string) => ({ queryKey: [userId], queryFn: () => api.getUser(userId), }), }); ``` ```typescript // queries/todos.ts export const todos = createQueryKeys('todos', { detail: (todoId: string) => [todoId], list: (filters: TodoFilters) => ({ queryKey: [{ filters }], queryFn: (ctx) => api.getTodos({ filters, page: ctx.pageParam }), }), }); ``` ```typescript // queries/index.ts export const queries = mergeQueryKeys(users, todos); ``` -------------------------------- ### Typing QueryFunctionContext with Inferred Keys (TypeScript) Source: https://github.com/lukemorales/query-key-factory/blob/main/README.md Illustrates how to use the inferred query key types (e.g., `QueryKeys['todos']['list']`) to provide strong typing for the `QueryFunctionContext` parameter in a `queryFn`, ensuring correct access to query key parts like filters. It also shows integration with `useQuery`. ```typescript import type { QueryKeys } from "../queries"; // import type { TodosKeys } from "../queries/todos"; type TodosList = QueryKeys['todos']['list']; // type TodosList = TodosKeys['list']; const fetchTodos = async (ctx: QueryFunctionContext) => { const [, , { filters }] = ctx.queryKey; return api.getTodos({ filters, page: ctx.pageParam }); } export function useTodos(filters: TodoFilters) { return useQuery({ ...queries.todos.list(filters), queryFn: fetchTodos, }); }; ``` -------------------------------- ### Updating Type Inference for New Output Structure (Diff) Source: https://github.com/lukemorales/query-key-factory/blob/main/CHANGELOG.md Illustrates the change in how helper types like inferQueryKeys work. Since the factory now always outputs an object, accessing the actual query key array requires accessing the queryKey property on the inferred type, rather than the type directly representing the key value. ```Diff type TodosKeys = inferQueryKeys; - type SingleTodoQueryKey = TodosKeys['todo']; + type SingleTodoQueryKey = TodosKeys['todo']['queryKey']; ``` -------------------------------- ### Optional Null Query Key Source: https://github.com/lukemorales/query-key-factory/blob/main/README.md Demonstrates how to define a query key entry where the `queryKey` property is explicitly set to `null`. This is useful when the key is not needed or handled differently. ```TypeScript export const users = createQueryKeys('users', { list: { queryKey: null, queryFn: () => api.getUsers(), } }); ``` -------------------------------- ### Access Serializable Key Scope Definition Source: https://github.com/lukemorales/query-key-factory/blob/main/README.md Illustrates how to access the full serializable `queryKey` for a specific instance (`users.detail(userId).queryKey`) and the base definition array for a key type (`users.detail._def`). This is useful for operations like cache invalidation. ```TypeScript users.detail(userId).queryKey; // => ['users', 'detail', userId] users.detail._def; // => ['users', 'detail'] ``` -------------------------------- ### Inferring Type of Full Query Key Store (TypeScript) Source: https://github.com/lukemorales/query-key-factory/blob/main/README.md Shows how to use `inferQueryKeyStore` with the type of the `queries` object created by `createQueryKeyStore` to generate a type alias (`QueryKeys`) representing the structure and types of all defined query keys. ```typescript import { createQueryKeyStore, inferQueryKeyStore } from "@lukemorales/query-key-factory"; export const queries = createQueryKeyStore({ /* ... */ }); export type QueryKeys = inferQueryKeyStore; ``` -------------------------------- ### Inferring Type of Merged Query Key Store (TypeScript) Source: https://github.com/lukemorales/query-key-factory/blob/main/README.md Demonstrates using `inferQueryKeyStore` with the type of the `queries` object created by `mergeQueryKeys` to generate a type alias (`QueryKeys`) for the combined query key structure, providing type safety across features. ```typescript // queries/index.ts import { mergeQueryKeys, inferQueryKeyStore } from "@lukemorales/query-key-factory"; import { users } from './users'; import { todos } from './todos'; export const queries = mergeQueryKeys(users, todos); export type QueryKeys = inferQueryKeyStore; ``` -------------------------------- ### Inferring Type of Feature-Specific Query Keys (TypeScript) Source: https://github.com/lukemorales/query-key-factory/blob/main/README.md Explains how to use `inferQueryKeys` with the type of a feature-specific query key object (like `todos` created by `createQueryKeys`) to generate a type alias (`TodosKeys`) representing only the keys defined within that feature. ```typescript import { createQueryKeys, inferQueryKeys } from "@lukemorales/query-key-factory"; export const todos = createQueryKeys('todos', { detail: (todoId: string) => [todoId], list: (filters: TodoFilters) => ({ queryKey: [{ filters }], queryFn: (ctx) => api.getTodos({ filters, page: ctx.pageParam }), }), }); export type TodosKeys = inferQueryKeys; ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.