Deep Dive into useSearchParams: Mastering Query String Manipulation
Tags: webdev, javascript, tutorial, react
Published: 2023-08-05 10:02:43

The rise of Server-side rendering (SSR) has gained popularity for a few reasons. One of the main benefits is improved performance and user experience. With SSR, the server generates the initial HTML content and sends it directly to the client, making the website or application load faster. This can reduce the time to first meaningful paint and improve SEO since search engines can easily crawl and index the content.

This has left popular libraries like React JS, looking for an answer. This is lead to the partnership of react, and next JS to develop a solution working together. This has lead to so awesome new hooks, among which one that often goes unnoticed is 'useSearchParams'. This client component hook lets you read the current URL's query string, making it easier than ever to manage URL parameters within your Next.js applications.

Let's start by examining the basics of the useSearchParams hook and how to implement it in your Next.js application.

## A Basic Example: The Search Bar

Consider the following TypeScript example of a search bar component, which uses useSearchParams to read the query string from the URL:

```typescript
'use client'
 
import { useSearchParams } from 'next/navigation'
 
export default function SearchBar() {
  const searchParams = useSearchParams()
 
  const search = searchParams.get('search')
 
  // URL -> `/dashboard?search=my-project`
  // `search` -> 'my-project'
  return <>Search: {search}</>
}
```
In the example above, useSearchParams returns a read-only version of the URLSearchParams interface. This interface provides several utility methods for reading and manipulating the URL's query string.

## Understanding the URLSearchParams Interface

When you call useSearchParams, it returns a read-only version of the URLSearchParams interface. This interface includes several utility methods such as get(), has(), getAll(), keys(), values(), entries(), forEach(), and toString(). 

Notably, the `get()` method returns the first value associated with the specified search parameter, while the `has()` method returns a boolean value indicating if a given parameter exists. 

Do note that useSearchParams is a Client Component hook and is not supported in Server Components. This is to prevent stale values during partial rendering, maintaining the freshness and accuracy of your data.

## Static Rendering and Dynamic Rendering

Static rendering and dynamic rendering are two significant aspects of how useSearchParams behaves. 

In statically rendered routes, calling useSearchParams will cause the tree up to the closest Suspense boundary to be client-side rendered. To reduce the portion of the route that is client-side rendered, you can wrap the component using useSearchParams in a Suspense boundary. 

For dynamically rendered routes, useSearchParams will be available on the server during the initial server render of the Client Component. You can force dynamic rendering by setting the dynamic route segment config option to force-dynamic.

## Server Components

In Pages (Server Components), you can access search params through the searchParams prop. However, Layouts (Server Components) do not receive this prop to prevent stale searchParams between navigations. In such cases, use the Page searchParams prop or the useSearchParams hook in a Client Component, which is re-rendered on the client with the latest searchParams.

## Updating searchParams

To set new searchParams, you can use useRouter or Link. After a navigation is performed, the current page.js will receive an updated searchParams prop. Here is an example:


```typescript
export default function ExampleClientComponent() {
  const router = useRouter()
  const pathname = usePathname()
  const searchParams = useSearchParams()!
 
  // Get a new searchParams string by merging the current
  // searchParams with a provided key/value pair
  const createQueryString = useCallback(
    (name: string, value: string) => {
      const params = new URLSearchParams(searchParams)
      params.set(name, value)
 
      return params.toString()
    },
    [searchParams]
  )
 
  return (
    <>
      <p>Sort By</p>
 
      {/* using useRouter */}
      <button
        onClick={() => {
          // <pathname>?sort=asc
          router.push(pathname + '?' + createQueryString('sort', 'asc'))
        }}
      >
        ASC
      </button>
 
      {/* using <Link> */}
      <Link
        href={
          // <pathname>?sort=desc
          pathname + '?' + createQueryString('sort', 'desc')
        }
      >
        DESC
      </Link>
    </>
  )
}
```

In conclusion, useSearchParams is a powerful tool in the Next.js arsenal, allowing you to elegantly handle URL query strings within your application. Understanding and mastering this hook will undoubtedly bring your Next.js development skills to the next level.