Next.js Suspense and cache
Unanswered
Buff-collared Nightjar posted this in #help-forum
Buff-collared NightjarOP
I am currently making a project using Next.js with MongoDB as the database. Inside my products page, I am fetching the products using a function
the
But if i remove the
Can anyone help me in coming up with a solution to the above said problem?
getProducts. The function is wrapped with React cache. I am calling this function twice, once in the Products Component and once inside Pagination Component. Both the components are children of Page Component of /src/app/products/page.tsx. I think there is a problem with the clashing suspense boundaries. I am using Suspense on the Products Component. But it does not show any loading skeleton. // /src/app/products/page.tsx
export default function Page({
searchParams,
}: {
searchParams: { page?: string; limit?: string; query?: string };
}) {
// parse the searchParams
return (
<>
<SearchBar initialQuery={query} />
<Suspense key={`${page}${query}`} fallback={<h1>Loading Products</h1>}>
<Products page={page} limit={limit} query={query} />
</Suspense>
<Pagination limit={limit} currentPage={page} query={query} />
</>
);
}Products Component uses getProducts which returns the products along with the number of items queried. (uses a $facet pipeline aggregation for MongoDB under the hood)the
Loading Products loader never appears when I perform a Search. The SearchBar is a simple search-bar which reads the input and pushes it into the URL.But if i remove the
Pagination Component, the loader appears as expected.Can anyone help me in coming up with a solution to the above said problem?
5 Replies
Siberian Flycatcher
Hey 👋
Since
Since
Pagination is not suspended, your Page component will have to wait for Pagination to fetch getProducts until it can render anything.Buff-collared NightjarOP
The reason I did not suspend
Pagination is because I do not want it to show a loader everytime I change a page. Is there a work around in a way that I can show the loader without affecting the pagination component?Siberian Flycatcher
Why do you need to fetch all products in
Pagination ? To get the number of pages?Buff-collared NightjarOP
So when the user is going to perform a search (using Atlas Search Index - full text search), it would change the number of pages, so yes, in order to get the total number of pages, I fetched the same resource again
Siberian Flycatcher
The most pragmatic solution could be to separate your DB queries.
Instead of using cached
In this case, your rendering will still get blocked by the query in Pagination, but at least it will be faster than fetching all data for products.
Instead of using cached
getProducts , fetch only the products list in the Products component and only the total number of products in Pagination.In this case, your rendering will still get blocked by the query in Pagination, but at least it will be faster than fetching all data for products.
async function Products({query}) {
const products = await db.collection("products").find({ /* query filters */})
return // Products JSX
}
async function Pagination({ limit, query }) {
const total = await db.products.countDocuments({ /* query filters */ })...
const numberOfPages = total / limit;
return // Pagination JSX
}