From 5d283d49d3f39c301b78e87a137057b7f1833197 Mon Sep 17 00:00:00 2001 From: Nate Kelley Date: Thu, 13 Feb 2025 14:28:45 -0700 Subject: [PATCH] query key updates --- web/.cursor/rules/api_buster_asset_rules.mdc | 39 +++++++++++++-- .../asset_interfaces/chat/chatQueryKeys.ts | 48 ------------------ .../api/asset_interfaces/chat/queryKeys.ts | 41 +++++++++++++++ .../collection/collectionQueryKeys.ts | 12 ----- .../asset_interfaces/collection/queryKeys.ts | 18 +++++++ .../asset_interfaces/dashboard/queryKeys.ts | 18 +++++++ web/src/api/asset_interfaces/queryKeys.ts | 10 ++-- .../api/asset_interfaces/users/queryKeys.ts | 10 ++++ .../useSocketQueryEmitOn.tsx | 7 ++- .../useSocketQueryMutation.tsx | 50 ++++--------------- .../ChatProvider/useChatAssosciations.ts | 11 ++-- .../useCollectionIndividual.ts | 13 +++-- .../CollectionListProvider.tsx | 6 ++- .../useBusterDashboardIndividual.ts | 32 ++++++------ web/src/context/Users/useFavoriteProvider.tsx | 45 ++++++----------- 15 files changed, 191 insertions(+), 169 deletions(-) delete mode 100644 web/src/api/asset_interfaces/chat/chatQueryKeys.ts create mode 100644 web/src/api/asset_interfaces/chat/queryKeys.ts delete mode 100644 web/src/api/asset_interfaces/collection/collectionQueryKeys.ts create mode 100644 web/src/api/asset_interfaces/collection/queryKeys.ts create mode 100644 web/src/api/asset_interfaces/dashboard/queryKeys.ts create mode 100644 web/src/api/asset_interfaces/users/queryKeys.ts diff --git a/web/.cursor/rules/api_buster_asset_rules.mdc b/web/.cursor/rules/api_buster_asset_rules.mdc index 72d9e367b..54a6c8ffb 100644 --- a/web/.cursor/rules/api_buster_asset_rules.mdc +++ b/web/.cursor/rules/api_buster_asset_rules.mdc @@ -2,7 +2,6 @@ description: Rules and guidelines for the asset_interfaces directory containing TypeScript interface definitions for all API responses globs: src/api/asset_interfaces/**/* --- - # API Asset Interfaces Directory Rules This directory (`src/api/asset_interfaces`) contains TypeScript interface definitions for all API responses. Each subdirectory represents a distinct API namespace. @@ -13,7 +12,8 @@ src/api/asset_interfaces/ ├── [namespace]/ │ ├── index.ts # Exports all interfaces and types │ ├── interfaces.ts # Contains type definitions -│ └── [other].ts # Optional additional type files +│ ├── queryKeys.ts # Contains query key definitions for TanStack Query +│ └── [other].ts # Optional additional type files ``` ## Rules and Guidelines @@ -21,6 +21,7 @@ src/api/asset_interfaces/ 1. Each namespace MUST have: - An `index.ts` file that exports all types - An `interfaces.ts` file containing type definitions + - A `queryKeys.ts` file that defines query key options for TanStack Query 2. Interface File (`interfaces.ts`) Requirements: - Must contain TypeScript interfaces, types, and enums for API responses @@ -32,12 +33,28 @@ src/api/asset_interfaces/ - Types: `TPascalCase` - Enums: `EPascalCase` -3. Index File (`index.ts`) Requirements: +3. Query Keys File (`queryKeys.ts`) Requirements: + - Defines reusable query keys and query options for TanStack React Query + - Uses `queryOptions` to create predefined query configurations + - Ensures consistent and structured key usage across API queries + - Example: + ```typescript + import { queryOptions } from '@tanstack/react-query'; + import type { BusterChat } from './chatInterfaces'; + + const chatsGetChat = (chatId: string) => + queryOptions({ + queryKey: ['chats', 'get', chatId] as const, + staleTime: 10 * 1000 + }); + ``` + +4. Index File (`index.ts`) Requirements: - Must re-export all types from `interfaces.ts` - Should not contain any type definitions - May include type utility functions if needed -4. General Guidelines: +5. General Guidelines: - Keep interfaces focused and single-responsibility - Use TypeScript's built-in utility types when appropriate - Document breaking changes in type definitions @@ -54,10 +71,22 @@ export interface IApiResponse { readonly message?: string; } +// queryKeys.ts +import { queryOptions } from '@tanstack/react-query'; +import type { IApiResponse } from './interfaces'; + +const fetchDataQuery = (id: string) => + queryOptions>({ + queryKey: ['data', 'fetch', id] as const, + staleTime: 60 * 1000 + }); + // index.ts export * from './interfaces'; +export * from './queryKeys'; ``` ## Purpose -This directory serves as the single source of truth for API response types across the application. It ensures type safety and provides proper TypeScript intellisense when working with API responses. +This directory serves as the single source of truth for API response types and query keys across the application. It ensures type safety, consistency, and provides proper TypeScript intellisense when working with API responses and queries. + diff --git a/web/src/api/asset_interfaces/chat/chatQueryKeys.ts b/web/src/api/asset_interfaces/chat/chatQueryKeys.ts deleted file mode 100644 index a0e09a80b..000000000 --- a/web/src/api/asset_interfaces/chat/chatQueryKeys.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { queryOptions, useQuery, useQueryClient } from '@tanstack/react-query'; -import type { BusterChat, BusterChatListItem } from './chatInterfaces'; -import type { GetChatListParams } from '@/api/request_interfaces/chats'; - -const chatsGetChat = (chatId: string) => - queryOptions({ - queryKey: ['chats', 'get', chatId] as const, - staleTime: 10 * 1000 - }); - -const chatsGetList = (filters?: GetChatListParams) => - queryOptions({ - queryKey: ['chats', 'list', filters] as const - }); - -const deleteChat = () => { - const queryKey = ['chats', 'list'] as const; - return queryOptions({ - queryKey - }); -}; - -export const chatQueryKeys = { - '/chats/get:getChat': chatsGetChat, - '/chats/list:getChatsList': chatsGetList, - '/chats/delete:deleteChat': deleteChat -}; - -const ExampleComponent = () => { - const queryClient = useQueryClient(); - const options = chatQueryKeys['/chats/get:getChat']!('123'); - const queryKey = options.queryKey; - - const data = queryClient.getQueryData(queryKey); - - const { data: data2 } = useQuery(options); - - queryClient.setQueryData(queryKey, (d) => { - return d; - }); - - const options2 = chatQueryKeys['/chats/delete:deleteChat']!(); - const queryKey2 = options2.queryKey; - - const data3 = queryClient.getQueryData(queryKey2); - - // -}; diff --git a/web/src/api/asset_interfaces/chat/queryKeys.ts b/web/src/api/asset_interfaces/chat/queryKeys.ts new file mode 100644 index 000000000..ae1c39d3c --- /dev/null +++ b/web/src/api/asset_interfaces/chat/queryKeys.ts @@ -0,0 +1,41 @@ +import { queryOptions, useQuery, useQueryClient } from '@tanstack/react-query'; +import type { BusterChat, BusterChatListItem } from './chatInterfaces'; +import type { GetChatListParams } from '@/api/request_interfaces/chats'; + +const chatsGetChat = (chatId: string) => + queryOptions({ + queryKey: ['chats', 'get', chatId] as const, + staleTime: 10 * 1000 + }); + +const chatsGetList = (filters?: GetChatListParams) => + queryOptions({ + queryKey: ['chats', 'list', filters] as const, + staleTime: 10 * 1000 + }); + +export const chatQueryKeys = { + '/chats/get:getChat': chatsGetChat, + '/chats/list:getChatsList': chatsGetList +}; + +// const ExampleComponent = () => { +// const queryClient = useQueryClient(); +// const options = chatQueryKeys['/chats/get:getChat']!('123'); +// const queryKey = options.queryKey; + +// const data = queryClient.getQueryData(queryKey); + +// const { data: data2 } = useQuery(options); + +// queryClient.setQueryData(queryKey, (d) => { +// return d; +// }); + +// const options2 = chatQueryKeys['/chats/list:getChatsList']!(); +// const queryKey2 = options2.queryKey; + +// const data3 = queryClient.getQueryData(queryKey2); + +// // +// }; diff --git a/web/src/api/asset_interfaces/collection/collectionQueryKeys.ts b/web/src/api/asset_interfaces/collection/collectionQueryKeys.ts deleted file mode 100644 index 0d40ed800..000000000 --- a/web/src/api/asset_interfaces/collection/collectionQueryKeys.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { queryOptions } from '@tanstack/react-query'; -import { BusterCollectionListItem } from './interfaces'; -import type { GetCollectionListParams } from '../../request_interfaces/collections'; - -const collectionsGetList = (filters?: GetCollectionListParams) => - queryOptions({ - queryKey: ['collections', 'list', filters] as const - }); - -export const collectionQueryKeys = { - '/collections/list:getCollectionsList': collectionsGetList -}; diff --git a/web/src/api/asset_interfaces/collection/queryKeys.ts b/web/src/api/asset_interfaces/collection/queryKeys.ts new file mode 100644 index 000000000..adf591ac6 --- /dev/null +++ b/web/src/api/asset_interfaces/collection/queryKeys.ts @@ -0,0 +1,18 @@ +import { queryOptions } from '@tanstack/react-query'; +import { BusterCollectionListItem, BusterCollection } from './interfaces'; +import type { GetCollectionListParams } from '../../request_interfaces/collections'; + +const collectionsGetList = (filters?: GetCollectionListParams) => + queryOptions({ + queryKey: ['collections', 'list', filters] as const + }); + +const collectionsGetCollection = (collectionId: string) => + queryOptions({ + queryKey: ['collections', 'get', collectionId] as const + }); + +export const collectionQueryKeys = { + '/collections/list:getCollectionsList': collectionsGetList, + '/collections/get:collectionState': collectionsGetCollection +}; diff --git a/web/src/api/asset_interfaces/dashboard/queryKeys.ts b/web/src/api/asset_interfaces/dashboard/queryKeys.ts new file mode 100644 index 000000000..a61731537 --- /dev/null +++ b/web/src/api/asset_interfaces/dashboard/queryKeys.ts @@ -0,0 +1,18 @@ +import { queryOptions } from '@tanstack/react-query'; +import type { BusterDashboard, BusterDashboardResponse } from './interfaces'; + +const dashboardGetList = queryOptions({ + queryKey: ['dashboard', 'list'] as const, + staleTime: 10 * 1000 +}); + +const dashboardGetDashboard = (dashboardId: string) => + queryOptions({ + queryKey: ['dashboard', 'get', dashboardId] as const, + staleTime: 10 * 1000 + }); + +export const dashboardQueryKeys = { + '/dashboards/get:getDashboardState': dashboardGetDashboard, + '/dashboards/list:getDashboardsList': dashboardGetList +}; diff --git a/web/src/api/asset_interfaces/queryKeys.ts b/web/src/api/asset_interfaces/queryKeys.ts index 9a15817d2..669d497d9 100644 --- a/web/src/api/asset_interfaces/queryKeys.ts +++ b/web/src/api/asset_interfaces/queryKeys.ts @@ -1,7 +1,11 @@ -import { chatQueryKeys } from './chat/chatQueryKeys'; -import { collectionQueryKeys } from './collection/collectionQueryKeys'; +import { chatQueryKeys } from './chat/queryKeys'; +import { collectionQueryKeys } from './collection/queryKeys'; +import { userQueryKeys } from './users/queryKeys'; +import { dashboardQueryKeys } from './dashboard/queryKeys'; export const queryKeys = { ...chatQueryKeys, - ...collectionQueryKeys + ...collectionQueryKeys, + ...userQueryKeys, + ...dashboardQueryKeys }; diff --git a/web/src/api/asset_interfaces/users/queryKeys.ts b/web/src/api/asset_interfaces/users/queryKeys.ts new file mode 100644 index 000000000..b97dfaeb3 --- /dev/null +++ b/web/src/api/asset_interfaces/users/queryKeys.ts @@ -0,0 +1,10 @@ +import { queryOptions } from '@tanstack/react-query'; +import { BusterUserFavorite } from './interfaces'; + +const favoritesGetList = queryOptions({ + queryKey: ['users', 'favorites', 'list'] as const +}); + +export const userQueryKeys = { + '/favorites/list:getFavoritesList': favoritesGetList +}; diff --git a/web/src/api/buster_socket_query/useSocketQueryEmitOn.tsx b/web/src/api/buster_socket_query/useSocketQueryEmitOn.tsx index 8d935e401..45e000c9b 100644 --- a/web/src/api/buster_socket_query/useSocketQueryEmitOn.tsx +++ b/web/src/api/buster_socket_query/useSocketQueryEmitOn.tsx @@ -16,9 +16,10 @@ export const useSocketQueryEmitOn = < socketResponse: TRoute, options: UseQueryOptions, callback?: (currentData: TData | null, newData: InferBusterSocketResponseData) => TData, - enabledTrigger?: boolean | string + enabledTriggerProp?: boolean | string ) => { const busterSocket = useBusterWebSocket(); + const enabledTrigger = enabledTriggerProp ?? true; const emitQueryFn = useMemoizedFn(async () => { busterSocket.emit(socketRequest); @@ -30,5 +31,7 @@ export const useSocketQueryEmitOn = < } }, [enabledTrigger]); - return useSocketQueryOn(socketResponse, options, callback); + const queryResult = useSocketQueryOn(socketResponse, options, callback); + + return { ...queryResult, refetch: emitQueryFn }; }; diff --git a/web/src/api/buster_socket_query/useSocketQueryMutation.tsx b/web/src/api/buster_socket_query/useSocketQueryMutation.tsx index 7b70b13ba..976aa7bda 100644 --- a/web/src/api/buster_socket_query/useSocketQueryMutation.tsx +++ b/web/src/api/buster_socket_query/useSocketQueryMutation.tsx @@ -1,13 +1,6 @@ 'use client'; -import { - type QueryFunction, - type QueryKey, - type UseQueryOptions, - type UseMutationOptions, - useMutation, - useQueryClient -} from '@tanstack/react-query'; +import { type UseQueryOptions, useMutation, useQueryClient } from '@tanstack/react-query'; import type { BusterSocketRequest, BusterSocketResponse, @@ -15,7 +8,6 @@ import type { } from '@/api/buster_socket'; import { useBusterWebSocket } from '@/context/BusterWebSocket'; import { useMemoizedFn } from 'ahooks'; -import { queryKeys } from '../asset_interfaces'; import type { BusterSocketRequestConfig, BusterSocketRequestRoute, @@ -23,7 +15,6 @@ import type { InferBusterSocketRequestPayload, InferBusterSocketResponseData } from './types'; -import type { BusterChatListItem } from '@/api/asset_interfaces/chat'; export function useSocketQueryMutation< TRequestRoute extends BusterSocketRequestRoute, @@ -36,10 +27,13 @@ export function useSocketQueryMutation< socketRequest: BusterSocketRequestConfig, socketResponse: BusterSocketResponseConfig, options?: UseQueryOptions, - preCallback?: (currentData: TQueryData | null, variables: TPayload) => TQueryData, - callback?: ( + preCallback?: ( currentData: TQueryData | null, - newData: InferBusterSocketResponseData + variables: TPayload + ) => TQueryData | Promise, + callback?: ( + newData: InferBusterSocketResponseData, + currentData: TQueryData | null ) => TQueryData ) { const busterSocket = useBusterWebSocket(); @@ -50,7 +44,7 @@ export function useSocketQueryMutation< if (queryKey && preCallback) { const currentData = queryClient.getQueryData(queryKey) ?? null; - const transformedData = preCallback(currentData, variables); + const transformedData = await preCallback(currentData, variables); queryClient.setQueryData(queryKey, transformedData); } @@ -70,7 +64,7 @@ export function useSocketQueryMutation< if (queryKey && callback) { const socketData = result as InferBusterSocketResponseData; const currentData = queryClient.getQueryData(queryKey) ?? null; - const transformedData = callback(currentData, socketData); + const transformedData = callback(socketData, currentData); queryClient.setQueryData(queryKey, transformedData); return result as TData; } @@ -85,29 +79,3 @@ export function useSocketQueryMutation< mutationFn }); } - -// const ExampleComponent = () => { -// const queryClient = useQueryClient(); -// const options = queryKeys['/chats/list:getChatsList'](); -// const data = queryClient.getQueryData(options.queryKey); -// data?.[0].created_by_avatar; - -// const { mutate } = useSocketQueryMutation< -// '/chats/delete', -// '/chats/delete:deleteChat', -// unknown, -// { id: string }[], -// { id: string }[], -// BusterChatListItem[] -// >( -// { route: '/chats/delete' }, -// { route: '/chats/delete:deleteChat' }, -// options, -// (currentData, newData) => { -// currentData?.[0].created_by_avatar; // This should now be properly typed -// return currentData ?? []; -// } -// ); - -// mutate([{ id: '123' }]); -// }; diff --git a/web/src/context/Chats/ChatProvider/useChatAssosciations.ts b/web/src/context/Chats/ChatProvider/useChatAssosciations.ts index ee0bd6c8a..16a9242fd 100644 --- a/web/src/context/Chats/ChatProvider/useChatAssosciations.ts +++ b/web/src/context/Chats/ChatProvider/useChatAssosciations.ts @@ -1,14 +1,17 @@ import { useMemoizedFn } from 'ahooks'; import { useBusterWebSocket } from '../../BusterWebSocket'; +import { useSocketQueryEmitAndOnce, useSocketQueryMutation } from '@/api/buster_socket_query'; export const useChatAssosciations = () => { const busterSocket = useBusterWebSocket(); + const x = useSocketQueryMutation(''); const onDeleteChat = useMemoizedFn(async (chatId: string) => { - await busterSocket.emit({ - route: '/chats/delete', - payload: { id: chatId } - }); + // + // await busterSocket.emit({ + // route: '/chats/delete', + // payload: { id: chatId } + // }); }); return { diff --git a/web/src/context/Collections/CollectionIndividualProvider/useCollectionIndividual.ts b/web/src/context/Collections/CollectionIndividualProvider/useCollectionIndividual.ts index 9c951ca9a..5ddd97e04 100644 --- a/web/src/context/Collections/CollectionIndividualProvider/useCollectionIndividual.ts +++ b/web/src/context/Collections/CollectionIndividualProvider/useCollectionIndividual.ts @@ -1,10 +1,15 @@ -import { useSocketQueryEmitOn } from '@/hooks'; +import { queryKeys } from '@/api/asset_interfaces'; +import { useSocketQueryEmitOn } from '@/api/buster_socket_query'; export const useCollectionIndividual = ({ collectionId }: { collectionId: string | undefined }) => { + const id = collectionId || ''; + const { data: collection, isFetched: isCollectionFetched } = useSocketQueryEmitOn( - { route: '/collections/get', payload: { id: collectionId || '' } }, - { route: '/collections/get:collectionState' }, - { enabled: !!collectionId } + { route: '/collections/get', payload: { id } }, + '/collections/get:collectionState', + queryKeys['/collections/get:collectionState'](id), + undefined, + !!id ); return { diff --git a/web/src/context/Collections/CollectionListProvider/CollectionListProvider.tsx b/web/src/context/Collections/CollectionListProvider/CollectionListProvider.tsx index f19f51825..5bfcf868a 100644 --- a/web/src/context/Collections/CollectionListProvider/CollectionListProvider.tsx +++ b/web/src/context/Collections/CollectionListProvider/CollectionListProvider.tsx @@ -1,11 +1,12 @@ import React, { useState } from 'react'; -import { useSocketQueryEmitOn } from '@/hooks'; +import { useSocketQueryEmitOn } from '@/api/buster_socket_query'; import type { CollectionsListEmit } from '@/api/buster_socket/collections'; import { ContextSelector, useContextSelector, createContext } from '@fluentui/react-context-selector'; +import { queryKeys } from '@/api/asset_interfaces'; type CollectionListFilters = Omit; @@ -18,7 +19,8 @@ export const useCollectionLists = () => { refetch: refetchCollectionList } = useSocketQueryEmitOn( { route: '/collections/list', payload: { page: 0, page_size: 1000, ...collectionListFilters } }, - { route: '/collections/list:listCollections' } + '/collections/list:listCollections', + queryKeys['/collections/list:getCollectionsList']() ); return { diff --git a/web/src/context/Dashboards/DashboardIndividualProvider/useBusterDashboardIndividual.ts b/web/src/context/Dashboards/DashboardIndividualProvider/useBusterDashboardIndividual.ts index 804536c35..8f97c4efd 100644 --- a/web/src/context/Dashboards/DashboardIndividualProvider/useBusterDashboardIndividual.ts +++ b/web/src/context/Dashboards/DashboardIndividualProvider/useBusterDashboardIndividual.ts @@ -1,9 +1,8 @@ -import { BusterDashboardResponse } from '@/api/asset_interfaces'; +import { BusterDashboardResponse, queryKeys } from '@/api/asset_interfaces'; import { useBusterAssetsContextSelector } from '@/context/Assets/BusterAssetsProvider'; import { useMemoizedFn } from 'ahooks'; -import React, { useEffect } from 'react'; import { useBusterMetricsIndividualContextSelector } from '@/context/Metrics'; -import { useSocketQueryEmitOn } from '@/hooks'; +import { useSocketQueryEmitOn } from '@/api/buster_socket_query'; export const useBusterDashboardIndividual = ({ dashboardId = '' @@ -18,23 +17,22 @@ export const useBusterDashboardIndividual = ({ const { data: dashboardResponse, refetch: refreshDashboard } = useSocketQueryEmitOn( { route: '/dashboards/get', payload: { id: dashboardId, password } }, - { route: '/dashboards/get:getDashboardState' }, - { enabled: !!dashboardId } + '/dashboards/get:getDashboardState', + queryKeys['/dashboards/get:getDashboardState'](dashboardId || ''), + (currentData, newData) => { + initializeDashboardMetrics(newData.metrics); + return newData; + }, + !!dashboardId ); - const initializeDashboard = useMemoizedFn((d: BusterDashboardResponse) => { - const metrics = d.metrics; - - for (const metric of metrics) { - onInitializeMetric(metric); + const initializeDashboardMetrics = useMemoizedFn( + (metrics: BusterDashboardResponse['metrics']) => { + for (const metric of metrics) { + onInitializeMetric(metric); + } } - }); - - useEffect(() => { - if (dashboardResponse) { - initializeDashboard(dashboardResponse); - } - }, [dashboardResponse]); + ); const dashboard = dashboardResponse?.dashboard; const metrics = dashboardResponse?.metrics || []; diff --git a/web/src/context/Users/useFavoriteProvider.tsx b/web/src/context/Users/useFavoriteProvider.tsx index e98e9effd..0f1cf4f69 100644 --- a/web/src/context/Users/useFavoriteProvider.tsx +++ b/web/src/context/Users/useFavoriteProvider.tsx @@ -1,54 +1,37 @@ import { useMemoizedFn } from 'ahooks'; -import { useSocketQueryEmitOn, useSocketQueryMutation } from '@/hooks'; +import { useSocketQueryEmitOn, useSocketQueryMutation } from '@/api/buster_socket_query'; +import { queryKeys } from '@/api/asset_interfaces'; export const useFavoriteProvider = () => { const { data: userFavorites, refetch: refreshFavoritesList } = useSocketQueryEmitOn( { route: '/users/favorites/list', payload: {} }, - { route: '/users/favorites/list:listFavorites' } + '/users/favorites/list:listFavorites', + queryKeys['/favorites/list:getFavoritesList'] ); const { mutate: addItemToFavorite } = useSocketQueryMutation( { route: '/users/favorites/post' }, { route: '/users/favorites/post:createFavorite' }, - { - preSetQueryData: [ - { - responseRoute: '/users/favorites/list:listFavorites', - callback: (prev, mutationParams) => [mutationParams, ...(prev || [])] - } - ] - } + queryKeys['/favorites/list:getFavoritesList'], + (prev, mutationParams) => [mutationParams, ...(prev || [])] ); const { mutate: removeItemFromFavorite } = useSocketQueryMutation( { route: '/users/favorites/delete' }, { route: '/users/favorites/post:createFavorite' }, - { - preSetQueryData: [ - { - responseRoute: '/users/favorites/list:listFavorites', - callback: (prev, mutationParams) => prev?.filter((f) => f.id !== mutationParams.id) || [] - } - ] - } + queryKeys['/favorites/list:getFavoritesList'], + (prev, mutationParams) => prev?.filter((f) => f.id !== mutationParams.id) || [] ); const { mutate: updateFavorites } = useSocketQueryMutation( { route: '/users/favorites/update' }, { route: '/users/favorites/update:updateFavorite' }, - { - awaitPrefetchQueryData: true, - preSetQueryData: [ - { - responseRoute: '/users/favorites/list:listFavorites', - callback: (prev, mutationParams) => { - return mutationParams.favorites.map((id, index) => { - let favorite = (prev || []).find((f) => f.id === id || f.collection_id === id)!; - return { ...favorite, index }; - }); - } - } - ] + queryKeys['/favorites/list:getFavoritesList'], + (prev, mutationParams) => { + return mutationParams.favorites.map((id, index) => { + const favorite = (prev || []).find((f) => f.id === id || f.collection_id === id)!; + return { ...favorite, index }; + }); } );