Next.js Discord

Discord Forum

How to show loaders when using router.push()

Unanswered
Brown bear posted this in #help-forum
Open in Discord
Brown bearOP
I have a server component for showing a list of products it is using searchParams, I have a filter component which is using router.replace(pathname?searchParams), on the server component I am doing data fetching to a third party not to my next server so it takes about 2 seconds to get a response, during this time I want to show a loader but it is not working neither the loader.tsx in page lever not the suspense fallback

both the FiltersSection and the ProductsSection are server component and are fetching the same data from the api which is wrapped in react cache()

Here is some minimal code

export async function Products({ searchParams }) {
  const { page, orderBy, ...searchFilters } = await searchParams;
  return (
    <section className="py-10 lg:py-20" id="product-listing">
      <div className="flex gap-6 flex-col lg:flex-row">
        <div className="w-full lg:w-1/4 flex-shrink-0">
          <FiltersSection
            page={page || 1}
            searchFilters={searchFilters}
            orderBy={orderBy}
          />
        </div>
        <div className="w-full lg:w-3/4">
          <Suspense fallback={<div>Loading...</div>}>
            <ProductsSection
              page={page || 1}
              searchFilters={searchFilters}
              orderBy={orderBy}
            />
          </Suspense>
        </div>
      </div>
    </section>
  );
}



This is the ProductsSection

export async function ProductsSection({
  page,
  searchFilters,
  orderBy,
}: {
  page: number | null;
  categoryId: string | undefined;
  searchFilters: Record<string, string> | undefined;
  orderBy: string | undefined;
  locale: string;
}) {
  const { products } = await getProducts(
    page,
    searchFilters,
    orderBy
  );

  return products.map(async (product) => {
    return <ProductCard key={product.id} {...product} />;
  });
}


I don't get it why I don't see the fallback

1 Reply

Siberian Flycatcher
You need to re-trigger the render of the Suspense by providing a unique key every time your filters change

export async function Products({ searchParams }) {
  const { page, orderBy, ...searchFilters } = await searchParams;
  return (
    <section className="py-10 lg:py-20" id="product-listing">
      <div className="flex gap-6 flex-col lg:flex-row">
        <div className="w-full lg:w-1/4 flex-shrink-0">
          <FiltersSection
            page={page || 1}
            searchFilters={searchFilters}
            orderBy={orderBy}
          />
        </div>
        <div className="w-full lg:w-3/4">
          <Suspense key={JSON.stringify(searchFilters)} fallback={<div>Loading...</div>}>
            <ProductsSection
              page={page || 1}
              searchFilters={searchFilters}
              orderBy={orderBy}
            />
          </Suspense>
        </div>
      </div>
    </section>
  );
}