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)