Skip to content

useSearchParams

Custom hook to manage URL search parameters.

Usage

tsx
import React from "react";
import { useSearchParams } from 'vhooks'; // Adjust the import path as needed

const SearchComponent = () => {
  const { params, updateSearchParams, clearSearchParams } = useSearchParams<{
    search: string;
    page: string;
  }>();

  return (
    <div>
      <h2>Search Parameters</h2>
      <p>Search: {params.search || "None"}</p>
      <p>Page: {params.page || "None"}</p>

      <button
        onClick={() => updateSearchParams({ search: "react", page: "1" })}
      >
        Set Search to "react"
      </button>
      <button onClick={clearSearchParams}>Clear Search Params</button>
    </div>
  );
};

export default SearchComponent;

Installation

sh
pnpm dlx scaflo@latest https://raw.githubusercontent.com/programming-with-ia/vDocs/scaflos/hooks/useSearchParams.json -e %src%/hooks
sh
npx scaflo@latest https://raw.githubusercontent.com/programming-with-ia/vDocs/scaflos/hooks/useSearchParams.json -e %src%/hooks
sh
bunx scaflo@latest https://raw.githubusercontent.com/programming-with-ia/vDocs/scaflos/hooks/useSearchParams.json -e %src%/hooks
sh
yarn dlx scaflo@latest https://raw.githubusercontent.com/programming-with-ia/vDocs/scaflos/hooks/useSearchParams.json -e %src%/hooks

API

useSearchParams<T>(): Object

Custom hook to manage URL search parameters.

Type parameters

NameTypeDescription
Textends Record<string, string>A record representing the expected search parameters.

Returns

Object

NameType
clearSearchParams() => void
getParams() => T
paramsT
updateSearchParams<Params>(newParams: Partial<Params>, clear?: boolean) => void

Hook

ts
import { useState, useEffect } from "react";

export function useSearchParams<T extends Record<string, string>>() {
    const getParams = () => {
    const searchParams = new URLSearchParams(window.location.search);
    const obj: Partial<T> = {};
    searchParams.forEach((value, key) => {
      obj[key as keyof T] = value as T[keyof T];
    });
    return obj as T;
  };

  const [params, setParams] = useState<T>(getParams);

  useEffect(() => {
        const handleUrlChange = () => {
      setParams(getParams());
    };

    // Override pushState and replaceState to detect SPA navigations
    const originalPushState = history.pushState;
    const originalReplaceState = history.replaceState;

    history.pushState = function (...args) {
      const result = originalPushState.apply(this, args);
      handleUrlChange();
      return result;
    };

    history.replaceState = function (...args) {
      const result = originalReplaceState.apply(this, args);
      handleUrlChange();
      return result;
    };

    // Listen to back/forward button
    window.addEventListener("popstate", handleUrlChange);

    // Cleanup function
    return () => {
      window.removeEventListener("popstate", handleUrlChange);
      history.pushState = originalPushState;
      history.replaceState = originalReplaceState;
    };
  }, []);

    const updateSearchParams = <Params extends T>(
    newParams: Partial<Params>,
    clear: boolean = false
  ) => {
    const searchParams = clear
      ? new URLSearchParams()
      : new URLSearchParams(window.location.search);
    Object.entries(newParams).forEach(([key, value]) => {
      if (value !== undefined && value !== null) {
        searchParams.set(key, value);
      }
    });
    const newUrl = `${window.location.pathname}?${searchParams.toString()}`;
    window.history.pushState({}, "", newUrl);
    setParams(getParams());
  };

    const clearSearchParams = () => {
    window.history.pushState({}, "", window.location.pathname);
    setParams({} as T);
  };

  return { params, updateSearchParams, clearSearchParams, getParams };
}

vDocs