DEV Community

Maaz Khan
Maaz Khan

Posted on • Originally published at maaz-khan.Medium

Sync Your React State with URL Search Parameters by Creating a Custom React Hook

In this post, I will introduce you to a custom React hook, useQueryState which you can think of as a useState hook with the additional capability of syncing with the query parameters of a URL. This would be very helpful if you'd like to keep the state across page reloads or share the state through the URL.

useQueryState Hook

import { Dispatch, SetStateAction, useEffect, useState } from "react";
import { useSearchParams } from "react-router-dom";

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

const useQueryState = <T>(
 param: string,
 initialValue: T
): UseQueryStateReturnType<T> => {
 const [searchParams, setSearchParams] = useSearchParams();

const paramValue = searchParams.get(param);
 let parsedValue: T;
 if (paramValue !== null) {
 parsedValue = JSON.parse(paramValue) as T;
 } else {
 parsedValue = initialValue;
 }

const [value, setValue] = useState<T>(parsedValue);

useEffect(() => {
 setSearchParams((prev) => {
 if (value !== null && value !== undefined && value !== "") {
 prev.set(param, JSON.stringify(value));
 } else prev.delete(param);
 return prev;
 });
 }, [value]);

return [value, setValue];
};

export default useQueryState;
Enter fullscreen mode Exit fullscreen mode

Usage

  1. Import useQueryState hook into your component
import useQueryState from "..../useQueryState";
Enter fullscreen mode Exit fullscreen mode
  1. Use within your component
const [searchValue, setSearchValue] = useQueryState<string>("param", "");
Enter fullscreen mode Exit fullscreen mode

Parameters

  1. param (string): The name of the query parameter.
  2. initialValue (T): The initial value, will be used when the query parameter is not present in the URL.

Return Value

An Array containing two items: current value and a setter function to update that value respectively

Example

import useQueryState from "..../useQueryState";

const Search = () => {
  const [searchValue, setSearchValue] = useQueryState<string>("search", "");

  return (
    <div className="App">
      <input
        onChange={(e) => setSearchValue(e.target.value)}
        value={searchValue}
        placeholder="Search"
      />
      <p>Search value is: {searchValue}</p>
    </div>
  );
};

export default Search;
Enter fullscreen mode Exit fullscreen mode

In this example, the searchValue state is automatically synced with the search query parameter in the URL.

Demo

See the interactive codesandbox demo:

Working Explanation

The useQueryState hook utilizes the useSearchParams hook from react-router-dom to manage URL query parameters. Here's a detailed breakdown of its functionality:

1. Initial State Setup:

  • If a query parameter is present in the URL for the specified key, its value is parsed and used as the initial state.
  • If the query parameter is not present, the provided initial value is used.

2. State Synchronization:

  • Whenever the state changes, the corresponding query parameter in the URL is updated.
  • If the state is set to an empty string, null, or undefined, the query parameter is removed from the URL.

3. Stringify and Parsing:

  • Since URL query parameters can only store strings, non-string values are stringified before being stored.
  • When retrieving the value from the URL, it is parsed back to its original form before being used as the initial state.

Top comments (0)