ReactHustle

How to Get NextJS Query Params Serverside (Typescript)

Jasser Mark Arioste

Jasser Mark Arioste

How to Get NextJS Query Params Serverside (Typescript)

Hello! In this tutorial, you'll learn how to get the NextJS query params in a server component using the /app router and also the older method ofgetServerSideProps.

The Problem #

Suppose you're using the /app router for your next js project and  want to use server-side rendering SSR for the route: /posts?page=2. You check the docs, and see that to get the search params, you can use use the useSearchParams hook, but the problem is it's a client component hook, available only on the client side. How do you get the search params in the server components?

How to Get the SearchParams in App Router #

To get the search parameters on the server, you can use the special file page.jsx/page.tsx. This is possible because the page.tsx component receives the following props object:

// app/posts/page.ts
type Props = {
  params: {},
  searchParams: { [key: string]: string | string[] | undefined },
}

export default function Page(props: Props) {
  const searchParams = props.searchParams;
  const page = searchParams.page;
  return <h1>My Page</h1>
}
1234567891011

Get the searchParams in a ServerComponent #

Unfortunately, you cannot directly get the searchParams in a ServerComponent. You have to get it from the page.tsx first and pass it to a  server component.

For example:

import MyServerComponent from "./MyServerComponent";

type Props = {
  params: {};
  searchParams: { [key: string]: string | string[] | undefined };
};

export default function Page(props: Props) {
  const searchParams = props.searchParams;

  return <MyServerComponent searchParams={searchParams}></MyServerComponent>;
}
123456789101112

And the server component definition should look something like this:

import React from "react";

type Props = {
  searchParams: { [key: string]: string | string[] | undefined };
};

const MyServerComponent = (props: Props) => {
  const searchParams = props.searchParams;
  return <div></div>;
};

export default MyServerComponent;
123456789101112

Defining the searchParams type #

You can also create your own type for the searchParams. If you look at the example above, we're using a mapped type. However, if you only expect certain values of search parameters, you can create your own definition to suit your needs. 

For example:

import MyServerComponent from "./MyServerComponent";

type PostsPageSearchParams = {
  page?: string;
  sort_by?: string;
  sort_order?: "asc" | "desc";
};
type Props = {
  params: {};
  searchParams: PostsPageSearchParams;
};

export default function Page(props: Props) {
  const searchParams = props.searchParams;
  console.log(searchParams.pages); // ❌ Error: Property 'pages' does not exist on type 'PostSearchParams'. Did you mean 'page'?
  return <MyServerComponent searchParams={searchParams}></MyServerComponent>;
}
1234567891011121314151617

Needless to say, this also helps to add the intellisense/autocomplete when using your editor and avoid typographical errors.

Getting the SearchParams on getServerSideProps: #

To get the query parameters on getServerSideProps, you can use ctx.query. The ctx.query object is of type ParsedUrlQuery, which is the same as seachParams on the app router.

type ParsedUrlQuery = { [key: string]: string | string[] | undefined };
1

Here's how to access it inside getServerSideProps:

import { GetServerSideProps } from "next";
import React from "react";

const SamplePage = () => {
  return <div>My Page</div>;
};

export default SamplePage;

export const getServerSideProps: GetServerSideProps = async (ctx) => {
  const query = ctx.query;
  const page = query.page;
  return {
    props: {
      page: page,
    },
  };
};
123456789101112131415161718

Defining a Custom ParsedUrlQuery #

Similar to our previous example, we can also define an extension of ParsedUrlQuery to create specific query parameters and avoid typographical errors. To make it work first, we have to create an interface or a type for all our query parameters, then use a type assertion.

import { GetServerSideProps } from "next";
import React from "react";

const SamplePage = () => {
  return <div>My Page</div>;
};

export default SamplePage;

interface SampleQuery {
  page?: string;
}

export const getServerSideProps: GetServerSideProps = async (ctx) => {
  const query = ctx.query as SampleQuery;
  const page = query.pages; // ❌ Error Property 'pages' does not exist on type 'SampleQuery'. Did you mean 'page'?
  return {
    props: {
      page: page,
    },
  };
};
12345678910111213141516171819202122

That's basically it!

Conclusion #

You learned how to get the searchParams object in a NextJS application for both the /app and /pages  router.

If you like this tutorial, please leave a like or share this article. For future tutorials like this, please subscribe to our newsletter or follow me on GitHub.

Resources #

Credits: Image by Melisa from Pixabay

Share this post!

Related Posts