It looks like the entire lifecycle of onQueryStarted occurs when fetchNextPage is called.
However, often fetchNextPage is expected to often indicate end-of-list.
This seems like unexpected behavior, because no additional base-query usage is made, but any side effects of onQueryStarted DO occur.
Take the following example, with the code below.
In this example, patchCachedUser syncs some metadata between the query-notifications endpoints with the get-user endpoint (the total notifications count, to prevent flickering while states reconcile).
The behavior that occurs is:
- Hook mounts with page of data.
onQueryStarted does not fire unless this is the first time the hook is mounted, as expected.
- The end of list is reached, triggering
fetchNextPage.
fetchNextPage, via getNextPageParam, knows we're at the end-of-list, returning undefined.
onQueryStarted is fired, ALWAYS. however, queryFulfilled is already resolved, and so it does the remaining work (e.g. pessimistic updates), using the old data.
getNotifications: build.infiniteQuery<
{
notifications: Notification[];
user: Pick<User, "numUnreadNotifications">
},
{
uid: string;
limit: number;
filter: "read" | "unread"
},
PaginationCursor | undefined
>({
onQueryStarted: async (args, { dispatch, queryFulfilled }) => {
try {
console.log("Fetching notifications for user:"); // THIS logs during a `fetchNextPage` call
const { data } = await queryFulfilled; // Base query has its own logging -- this is already resolved during the calls.
const lastPage = data.pages[data.pages.length - 1];
const user = lastPage.user;
dispatch(patchCachedUser(args, user)); // This now badly assumes that the data is the most-recent from the API, but its from a previous cached call.
} catch (error) {
void error;
}
},
infiniteQueryOptions: {
initialPageParam: undefined,
getNextPageParam: ({
notifications: lastPage,
}): undefined | PaginationCursor => {
const lastItem = lastPage?.at(-1);
return lastItem && { createdAt: lastItem.createdAt };
},
},
This looks like unexpected behavior to me, and I don't see a clean way to get around this (to prevent side affects from occuring multiple times from the same resolved underlying queryFulfilled)
It looks like the entire lifecycle of
onQueryStartedoccurs whenfetchNextPageis called.However, often
fetchNextPageis expected to often indicate end-of-list.This seems like unexpected behavior, because no additional base-query usage is made, but any side effects of
onQueryStartedDO occur.Take the following example, with the code below.
In this example,
patchCachedUsersyncs some metadata between thequery-notificationsendpoints with theget-userendpoint (the total notifications count, to prevent flickering while states reconcile).The behavior that occurs is:
onQueryStarteddoes not fire unless this is the first time the hook is mounted, as expected.fetchNextPage.fetchNextPage, viagetNextPageParam, knows we're at the end-of-list, returning undefined.onQueryStartedis fired, ALWAYS. however,queryFulfilledis already resolved, and so it does the remaining work (e.g. pessimistic updates), using the old data.This looks like unexpected behavior to me, and I don't see a clean way to get around this (to prevent side affects from occuring multiple times from the same resolved underlying
queryFulfilled)