Sync React State with URL Search Parameters
Tags: react, reacthooks, reactrouter, codesnippet
Published: 2024-01-30 16:30:19

Effortlessly synchronizing a React component's state with URL search parameters can be a common requirement when working with React applications that utilize React Router. In such scenarios, the `useQueryParamsState` hook provides an elegant solution, streamlining the management of URL query parameters.

## Installation

To get started, ensure you have React and React Router installed in your project:

```bash
npm install react react-router-dom
```

## 'useQueryParamsState' hook


```jsx
import { useState, useEffect, Dispatch, SetStateAction } from "react";
import { useLocation } from "react-router-dom";

type UseQueryParamsStateReturnType<T> = [T, Dispatch<SetStateAction<T>>];

export const useQueryParamsState = <T>(
  param: string,
  initialState: T
): UseQueryParamsStateReturnType<T> => {
  const location = useLocation();

  // State for managing the value derived from the query parameter
  const [value, setValue] = useState<T>(() => {
    if (typeof window === "undefined") return initialState;

    // Parse query parameter value from the URL
    const { search } = window.location;
    const searchParams = new URLSearchParams(search);
    const paramValue = searchParams.get(param);

    return paramValue !== null ? JSON.parse(paramValue) as T : initialState;
  });

  useEffect(() => {
    const currentSearchParams = new URLSearchParams(window.location.search);

    // Update the query parameter with the current state value
    if (value !== null && value !== "") {
      currentSearchParams.set(param, JSON.stringify(value));
    } else {
      // Remove the query parameter if the value is null or empty
      currentSearchParams.delete(param);
    }

    // Update the URL with the modified search parameters
    const newUrl = [window.location.pathname, currentSearchParams.toString()]
      .filter(Boolean)
      .join("?");

    // Update the browser's history without triggering a page reload
    window.history.replaceState(window.history.state, "", newUrl);
  }, [param, value, location.pathname]);

  return [value, setValue];
};
```

## Usage

1. Import the `useQueryParamsState` hook into your component:

```jsx
import { useQueryParamsState } from './path-to/useQueryParamsState';
```

2. Use the hook within your component:

   ```jsx
const MyComponent: React.FC = () => {
  const [paramValue, setParamValue] = useQueryParamsState<string>('myQueryParam', 'default');

  // Use paramValue and setParamValue as needed in your component
  return (
       // Your component JSX
  );
   ```


## Parameters

- `param` (string): The name of the query parameter you want to sync with the component state.
- `initialState` (T): The initial state for the component. This will be used when the query parameter is not present in the URL.


## Return Value

The hook returns a tuple containing the current value of the query parameter and a function to update that value.

```typescript
type UseQueryParamsStateReturnType<T> = [T, Dispatch<SetStateAction<T>>];
```


## Example

Consider a component that manages a search term based on a query parameter:

```jsx
import { useQueryParamsState } from './path-to/useQueryParamsState';

const SearchComponent: React.FC = () => {
  const [searchTerm, setSearchTerm] = useQueryParamsState<string>('search', '');

  return (
    <div>
      <label>Search Term:</label>
      <input
        type="text"
        value={searchTerm}
        onChange={(e) => setSearchTerm(e.target.value)}
      />
      <p>Search Term: {searchTerm}</p>
    </div>
  );
};

```

In this example, the `SearchComponent` automatically syncs its state with the 'search' query parameter in the URL, allowing users to bookmark or share specific search states.

## Demo

Explore the interactive demo on CodeSandbox to see the `useQueryParamsState` hook in action:

[![Open in CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/p/sandbox/react-ts-use-query-params-state-hook-forked-gfztc2)


## Explanation

The `useQueryParamsState` hook leverages React's state and effect hooks along with React Router's `useLocation` to manage the state of a specific query parameter. It handles parsing and updating the URL, providing a clean and reusable solution for components that need to interact with query parameters in a React Router environment. Developers can use this hook to create components that maintain their state based on URL query parameters without manually handling the complexities of URL manipulation.

Thanks For Reading 😉