How to access query parameters in Next.js 13.4 with the new app router?
Asked Answered
A

1

14

I'm using the latest version of Next.js (13.4) with the new app router.

In my application, I have a Link component with a button inside a ../components/products.tsx file.

Each product has a "details" button that navigates to a dynamic route using the Link component. I'm passing query parameters along with the route using the pathname and query properties of the Link component.

Here's an example of the Link component in the ../components/products.tsx file:

<Link href={{
                  pathname:`product/${item._id}`,
                  query:{
                    _id: item._id,
                    title: item.title,
                    description: item.description,
                    oldPrice: item.oldPrice,
                    price: item.price,
                    brand: item.brand,
                    image: item.image,
                    isNew: item.isNew,
                    category: item.category,
                  },
                }}
                as ={`product/${item._id}`}
                >

In the dynamic route component (page.tsx) with the path app/product/[id], I want to access the query parameters and render them on the page. Here's an example of the page.tsx file:

import React from 'react';
import { useRouter } from 'next/router';

const ProductPage = () => {
  const router = useRouter();
  const query = router.query;

  return (
    <div>
      <h1>Product Details</h1>
      <p>ID: {query._id}</p>
      <p>Title: {query.title}</p>
      <p>Description: {query.description}</p>
      <p>Old Price: {query.oldPrice}</p>
      <p>Price: {query.price}</p>
      <p>Brand: {query.brand}</p>
      <p>Image: {query.image}</p>
      <p>Is New: {query.isNew}</p>
      <p>Category: {query.category}</p>
    </div>
  );
};

export default ProductPage;

The problem I'm facing is that router.query doesn't work with the new app router in Next.js 13.4.

I'm looking for a solution to access the query parameters in the new app router of Next.js 13.4. Any help or suggestions would be greatly appreciated. Thank you

I've tried using searchParams, useSearchParams, and usePathname, but I'm unable to retrieve the query parameters.

Amain answered 1/7, 2023 at 0:11 Comment(0)
O
14

next/router is for pages and next/navigation is for app router

import { useRouter } from 'next/navigation';

With that said, you don't need it as it will not return the query params. You need to use the useSearchParams hook or searchParams prop (see option 2).


Client component (option 1)

'use client'

import { useSearchParams } from 'next/navigation'

export const ProductCard = () => { // this is a component not a page see below
  const searchParams = useSearchParams();

  const id = searchParams.get('_id');
  const title = searchParams.get('title');
  const description = searchParams.get('description');

  return (
    <div>
      <h1>Product Details</h1>
      <p>ID: {id}</p>
      <p>Title: {title}</p>
      <p>Description: {description}</p>
    </div>
  );
};

If a route is statically rendered, calling useSearchParams will cause the tree up to the closest Suspense boundary to be client-side rendered.

This allows a part of the page to be statically rendered while the dynamic part that uses searchParams is client-side rendered.

You can reduce the portion of the route that is client-side rendered by wrapping the component that uses useSearchParams in a Suspense boundary. For example:

import { Suspense } from 'react';
import { ProductCard } from './product-card';
 
const ProductCardFallback = () => <>your loader</>
 
const ProductPage = () => (
  <Suspense fallback={ProductCardFallback}>
   <ProductCard />
  </Suspense>
);

export default ProductPage;

Server page (option 2)

If it's a server rendered page you can access the params using the pages's searchParams prop.

const ProductPage = ({ searchParams }) => (
   <div>
     <h1>Product Details</h1>
     <p>ID: {searchParams._id}</p>
     <p>Title: {searchParams.title}</p>
     <p>Description: {searchParams.description}</p>
   </div>
 );

The options are likely not interchangeable. They each have their own use that depends on your application and setup.

Ornithomancy answered 1/7, 2023 at 3:9 Comment(4)
Thank You very much.The first option did the job.I did try that on my own before asking the question, but all i was getting nulls in the console when trying to console.log the searchParams(' '),i guess i didnt do something right.. Thanks again! Sorry i cant upvote.I need 15 reputation, i have only 11 xDAmain
Also what i noticed is that this was wrong in my code : . . . as ={product/${item._id}} . . . When i have this in my code, i got only nulls, when i removed it ,i get the query, with the code you gave me!Amain
but sir what if i just want to pass a complete object at once rather than passing one by one as in the question you have passes the values one by one in query?? Can not i pass the entire object at once???Untold
Query params must be strings. You could JSON.stringify() and then decode it with JSON.parse()Ornithomancy

© 2022 - 2024 — McMap. All rights reserved.