(hook) 객체를 URL queryparam으로 변경하는 hook

12/9/2024

'use client';

import { useEffect, useState, useMemo } from 'react';

import { usePathname, useRouter, useSearchParams } from 'next/navigation';

type UseCustomSearchParamsProps = object;

const useCustomSearchParams = <T extends Record<string, any>>(defaultParams: UseCustomSearchParamsProps) => {
  const router = useRouter();
  const pathname = usePathname();
  const _searchParams = useSearchParams();

  // Parse URL search params
  const urlSearchParams = useMemo(() => {
    const params = new URLSearchParams(_searchParams.toString());
    return Object.fromEntries(params.entries()) as T;
  }, [_searchParams]);

  // Initialize local search params
  const [localSearchParams, setLocalSearchParams] = useState<T>(() => {
    const params = new URLSearchParams(_searchParams.toString());
    for (const [key, value] of Object.entries(defaultParams)) {
      if (!params.has(key)) {
        params.set(key, String(value));
      }
    }
    return Object.fromEntries(params.entries()) as T;
  });

  useEffect(() => {
    update();
  }, []);

  const [shouldUpdate, setShouldUpdate] = useState(false);

  const setSearchParams = (newParams: Partial<T>, isUpdate: boolean = false): void => {
    setLocalSearchParams((prev) => ({
      ...prev,
      ...newParams,
    }));
    if (isUpdate) {
      setShouldUpdate(true);
    }
  };

  useEffect(() => {
    if (shouldUpdate) {
      update();
      setShouldUpdate(false);
    }
  }, [localSearchParams, shouldUpdate]);

  // Update the URL
  const update = () => {
    const params = new URLSearchParams();
    for (const [key, value] of Object.entries(localSearchParams)) {
      if (value !== undefined) {
        params.set(key, String(value));
      } else {
        params.delete(key);
      }
    }
    router.replace(`${pathname}?${params.toString()}`, { scroll: false });
  };

  // Check if localSearchParams differ from urlSearchParams
  const isChanged = useMemo(() => {
    return JSON.stringify(localSearchParams) !== JSON.stringify(urlSearchParams);
  }, [localSearchParams, urlSearchParams]);

  return {
    searchParams: localSearchParams,
    urlSearchParams,
    setSearchParams,
    update,
    isChanged,
  };
};

export default useCustomSearchParams;

© 2025 Mingu Kim. All rights reserved.