'How can I get (query string) parameters from the URL in Next.js?

When I click on a link in my /index.js, it brings me to /about.js page.

However, when I'm passing parameter name through URL (like /about?name=leangchhean) from /index.js to /about.js, I don't know how to get it in the /about.js page.

index.js

import Link from 'next/link';
export default () => (
  <div>
    Click{' '}
    <Link href={{ pathname: 'about', query: { name: 'leangchhean' } }}>
      <a>here</a>
    </Link>{' '}
    to read more
  </div>
);


Solution 1:[1]

Use router-hook.

You can use the useRouter hook in any component in your application.

https://nextjs.org/docs/api-reference/next/router#userouter

pass Param

import Link from "next/link";

<Link href={{ pathname: '/search', query: { keyword: 'this way' } }}><a>path</a></Link>
Or
import Router from 'next/router'

Router.push({
    pathname: '/search',
    query: { keyword: 'this way' },
})

In Component

import { useRouter } from 'next/router'

export default () => {
  const router = useRouter()
  console.log(router.query);

  ...
}

Solution 2:[2]

Using Next.js 9 or above you can get query parameters:

With router:

import { useRouter } from 'next/router'

const Index = () => {
  const router = useRouter()
  const {id} = router.query

  return(<div>{id}</div>)
}

With getInitialProps:

const Index = ({id}) => {
  return(<div>{id}</div>)
}

Index.getInitialProps = async ({ query }) => {
  const {id} = query

  return {id}
}

Solution 3:[3]

url prop is deprecated as of Next.js version 6: https://github.com/zeit/next.js/blob/master/errors/url-deprecated.md

To get the query parameters, use getInitialProps:

For stateless components

import Link from 'next/link'
const About = ({query}) => (
  <div>Click <Link href={{ pathname: 'about', query: { name: 'leangchhean' }}}><a>here</a></Link> to read more</div>
)

About.getInitialProps = ({query}) => {
  return {query}
}

export default About;

For regular components

class About extends React.Component {

  static getInitialProps({query}) {
    return {query}
  }

  render() {
    console.log(this.props.query) // The query is available in the props object
    return <div>Click <Link href={{ pathname: 'about', query: { name: 'leangchhean' }}}><a>here</a></Link> to read more</div>

  }
}

The query object will be like: url.com?a=1&b=2&c=3 becomes: {a:1, b:2, c:3}

Solution 4:[4]

For those looking for a solution that works with static exports, try the solution listed here: https://github.com/zeit/next.js/issues/4804#issuecomment-460754433

In a nutshell, router.query works only with SSR applications, but router.asPath still works.

So can either configure the query pre-export in next.config.js with exportPathMap (not dynamic):

    return {
      '/': { page: '/' },
      '/about': { page: '/about', query: { title: 'about-us' } }
    }
  }

Or use router.asPath and parse the query yourself with a library like query-string:

import { withRouter } from "next/router";
import queryString from "query-string";

export const withPageRouter = Component => {
  return withRouter(({ router, ...props }) => {
    router.query = queryString.parse(router.asPath.split(/\?/)[1]);

    return <Component {...props} router={router} />;
  });
};

Solution 5:[5]

If you need to retrieve a URL query from outside a component:

import router from 'next/router'

console.log(router.query)

Solution 6:[6]

I know 2 ways to do this:
A Server-Side way, and a Client-Side way.

Method #1: SSR (Server-Side Rendering):

You should use Query Context for that page.
So use getServerSideProps instead of getStaticProps

import React from "react";

export async function getServerSideProps(context) {
    const page = (parseInt(context.query.page) || 1).toString();
    // Here we got the "page" query parameter from Context
    // Default value is "1"
  
    const res = await fetch(`https://....com/api/products/?page=${page}`);
    const products = await res.json();
    return {props: {products: products.results}}
    // will be passed to the page component as props
  }

const Page = (props) =>{
    const products = props.products;
    return (
      <ul>
        {products.map((product) => (
            <li key={product.id}>{product.name}</li>
        ))}
      </ul>);
}

export default Page

The reason is that: this data cannot be pre-rendered ahead of user's request, so it must be Server-Side Rendered (SSR) on every request.

  • Static Pages: Use getStaticProps
  • Changing Content: use getServerSideProps
    And here the content is changing based on query Parameters

Reference: https://nextjs.org/docs/api-reference/data-fetching/get-server-side-props

Method #2: Next Router (Client Side):

import {useState, useEffect} from "react";
import { useRouter } from 'next/router'

const Page = () =>{
    const [products, setProducts] = useState([]);
    const [page, setPage] =useState((useRouter().query.page || 1).toString());
    // getting the page query parameter
    // Default value is equal to "1"

    useEffect(()=>{
      (async()=>{
        const res = await fetch(`https://....com/api/products/?page=${page}`);
        const products = await res.json();
        setProducts(products.results);
        // This code will be executed only once at begining of the loading of the page
        // It will not be executed again unless you cahnge the page
      })()
    },[page]);

    return (
      <ul>
        {products.map((product) => (
            <li key={product.id}>{product.name}</li>
        ))}
      </ul>
      );
}

export default Page

Reference: https://nextjs.org/docs/api-reference/next/router

Solution 7:[7]

import { useRouter } from 'next/router';

function componentName() {
    const router = useRouter();
    console.log('router obj', router);
}

We can find the query object inside a router using which we can get all query string parameters.

Solution 8:[8]

Using {useRouter} from "next/router"; helps but sometimes you won't get the values instead u get the param name itself as value. This issue happens when u are trying to access query params via de-structuring like:

let { categoryId = "", sellerId = "" } = router.query;

and the solution that worked for me is try to access the value directly from query object:

let categoryId  = router.query['categoryId'] || '';
let sellerId  = router.query['sellerId'] || '';

Solution 9:[9]

Post.getInitialProps = async function(context) {

  const data = {}
  try{
    data.queryParam = queryString.parse(context.req.url.split('?')[1]);
  }catch(err){
    data.queryParam = queryString.parse(window.location.search);
  }
  return { data };
};