In Next.js I'm using a Server Component to preload data into a Client Component using preloadQuery and useSuspenseQuery. If javascript is enabled, the Client Component uses fetchMore + offsetLimitPagination() to do an infinite scroll. This all works fine.
When javascript is disabled, a classic link-based pagination is displayed which uses a page url query to display each page of results. The page query string value is passed to the component and used to set the offset variable before the query is executed.
Server component:
export default function RecipeEntriesList({ pageNum }: { pageNum: number }) {
// query variables are initialized in the
// Server Component then passed to the Client Component
const queryLimit = 10;
const queryVariables: QueryVariables = {
section: ["recipes"],
limit: queryLimit,
offset: (pageNum - 1) * queryLimit, // 0 if on the first page
};
return (
<PreloadQuery query={GET_RECIPE_ENTRIES} variables={{ queryVariables }}>
<RecipeEntriesListClient queryVariables={queryVariables} />
</PreloadQuery>
);
}
Client component:
export default function RecipeEntriesListClient({
queryVariables,
}: {
queryVariables: QueryVariables;
}) {
// offset is mutable in the client component
// so we copy the initial value into a ref
const queryOffset = useRef(queryVariables.offset);
const { data, error, networkStatus, fetchMore } =
useSuspenseQuery<RecipeListingQuery>(GET_RECIPE_ENTRIES, {
variables: queryVariables, // defined in the Recipe Entries server component
});
const inViewRef = useOnInView((inView) => {
if (inView && data && data.recipeList.length < data.entryCount) {
fetchMore({
variables: {
offset: (queryOffset.current = data.recipeList.length),
},
});
}
});
// ...
This does not work as expected. The entries from page 1 are displayed no matter which page query string is being accessed. I assume this has to do with how Apollo is caching the entries, but I don't know what I'm doing wrong. I have a separate InMemoryCache for the server component that lists offset as a keyArg but it doesn't seem to have an effect:
const keyArgs = ["section", "offset"];
const queryCache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
entries: {
keyArgs: keyArgs
},
entryCount: {
keyArgs: keyArgs,
},
},
},
},
});
I'm surprised this is happening since the server cache gets thrown out immediately anyway so I don't really understand what's wrong. Here's a CodeSandbox with the full setup.
In Next.js I'm using a Server Component to preload data into a Client Component using
preloadQueryanduseSuspenseQuery. If javascript is enabled, the Client Component usesfetchMore+offsetLimitPagination()to do an infinite scroll. This all works fine.When javascript is disabled, a classic link-based pagination is displayed which uses a
pageurl query to display each page of results. Thepagequery string value is passed to the component and used to set theoffsetvariable before the query is executed.Server component:
Client component:
This does not work as expected. The entries from page 1 are displayed no matter which page query string is being accessed. I assume this has to do with how Apollo is caching the entries, but I don't know what I'm doing wrong. I have a separate
InMemoryCachefor the server component that listsoffsetas a keyArg but it doesn't seem to have an effect:I'm surprised this is happening since the server cache gets thrown out immediately anyway so I don't really understand what's wrong. Here's a CodeSandbox with the full setup.