Simplifying React Router Query Parameter Management with Custom Hooks
Tags: react, developers, coders, webdev
Published: 2024-04-08 13:07:32

Managing query parameters in a React application can be challenging, especially when you need to synchronize them with your component's state. 

React Router provides hooks like `useLocation` and `useSearchParams` to help with this, but managing them together can still be complex. 

In this blog post, we'll introduce an enhanced custom hook, useQueryParams, that simplifies the management of query parameters and adds a new feature to remove query parameters from the URL.

## Introducing `useQueryParams` Custom Hook

The `useQueryParams` custom hook combines the functionality of useLocation, useSearchParams, and adds the ability to manage query parameters more effectively. It provides four main functionalities:

1. **Accessing All Query Parameters:** Easily access all query parameters and their values as an object.
2. **Accessing a Specific Query Parameter:** Get the value of a specific query parameter by its key.
3. **Updating Query Parameters:** Update the value of a query parameter, which automatically updates the browser's URL.
4. **Removing Query Parameters:** Remove a query parameter from the URL by its key.

## Hook Implementation:
Create a `useQueryParams.ts` file in `src/hooks` folder:

```
import { useEffect, useState } from "react";
import { useLocation, useSearchParams } from "react-router-dom";

export default function useQueryParams() {
  const location = useLocation();
  const [searchParams, setSearchParams] = useSearchParams();
  const [allQueryParams, setAllQueryParams] = useState(Object.fromEntries(searchParams));

  useEffect(() => {
    setAllQueryParams(Object.fromEntries(searchParams));
  }, [searchParams]);

  const getQueryParamByKey = (key: string) => {
    const params = new URLSearchParams(location.search);
    return params.get(key) || "";
  };

  const setQueryParam = (key :string, value: string) => {
    const params = new URLSearchParams(location.search);
    params.set(key, value.toString());
    setSearchParams(params.toString());
  };

  const removeQueryParamByKey = (key: string) => {
    const params = new URLSearchParams(location.search);
    params.delete(key);
    setSearchParams(params.toString());
  };

  return {
    allQueryParams,
    getQueryParamByKey,
    setQueryParam,
    removeQueryParamByKey,
  };
}

```

## How to Use `useQueryParams` Hook
To use the `useQueryParams` hook, follow these steps:

- **Import the Hook:**

```
import useQueryParams from './hooks/useQueryParams';
```

- **Accessing All Query Parameters:**

```
const { allQueryParams } = useQueryParams();
```
This gives you an object containing all query parameters and their values.

- **Accessing a Specific Query Parameter:**

```
const searchTerm = getQueryParamByKey('search');
const currentPage = getQueryParamByKey('page');
```
This retrieves the value of a specific query parameter by its key.

- **Updating Query Parameters:**

```
setQueryParam('search', 'react hooks');
setQueryParam('page', 2);
```
This updates the value of a query parameter, which will reflect in the browser's URL.

- **Removing Query Parameters:**

```
removeQueryParamByKey('page');
```
This removes the page query parameter from the URL.

## Example Usage
Here's a simple example demonstrating the usage of the `useQueryParams` hook in a React component:

**`App.tsx`**
```
import { ChangeEvent, useEffect, useState } from 'react';
import useQueryParams from './hooks/useQueryParams';

function App() {
  const { allQueryParams, getQueryParamByKey, setQueryParam, removeQueryParamByKey } =
    useQueryParams();

  const [input, setInput] = useState<string>(getQueryParamByKey('search'));
  const [page, setPage] = useState<number>(Number(getQueryParamByKey('page')));

  useEffect(() => {
    setQueryParam('search', input);
  }, [input]);

  useEffect(() => {
    setQueryParam('page', page.toString());
  }, [page]);

  return (
    <div>
      <h1>All Query Params:</h1>
      <pre>{JSON.stringify(allQueryParams)}</pre>
      <h1>Query Param by Key:</h1>
      <span>Search Box : </span>
      <input
        type="text"
        value={input}
        onChange={(event: ChangeEvent<HTMLInputElement>) => {
          setInput(event.target.value);
        }}
      />
      <div>
        <button
          onClick={() => {
            page > 0 && setPage(page - 1);
          }}
        >
          {'<'}
        </button>
        <span> Current Page: {getQueryParamByKey('page')} </span>
        <button
          onClick={() => {
            setPage(page + 1);
          }}
        >
          {'>'}
        </button>
      </div>
      <h1> Remove query param </h1>
      <button
          onClick={() => {
            removeQueryParamByKey('page')
          }}
        >Revome page
        </button>
        <button
          onClick={() => {
            removeQueryParamByKey('search')
          }}
        >Remove search
        </button>

    </div>
  );
}

export default App;

```
To use the `useQueryParams` custom hook with React Router, make sure you wrap your application in a `BrowserRouter` component. This is required for the `useLocation` and `useSearchParams` hooks to work correctly. Here's how you can add the BrowserRouter to your application:

**`main.tsx`**
```
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App.tsx';
import { BrowserRouter, Route, Routes } from 'react-router-dom';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <BrowserRouter>
      <Routes>
        <Route path={'/'} element={<App />} />
      </Routes>
    </BrowserRouter>
  </React.StrictMode>
);

```

## Conclusion
Managing query parameters in a React application can be simplified with the `useQueryParams` custom hook. By encapsulating the logic for accessing, updating, and removing query parameters, this hook provides a cleaner and more maintainable approach to handling query parameters in your React components. Try it out in your next project and streamline your query parameter management!

Happy Coding 😊!