import { useEffect, useCallback } from 'react'; import { useSearchParams } from 'react-router-dom'; /** * Sync state with URL search params * @param {Object} state - Current state object * @param {Function} setState - State setter function * @param {Object} defaultState - Default state values * @param {Array} keys - Keys to sync with URL */ export function useUrlState(state, setState, defaultState, keys) { const [searchParams, setSearchParams] = useSearchParams(); // Initialize state from URL on mount useEffect(() => { const urlState = {}; let hasUrlParams = false; keys.forEach(key => { const value = searchParams.get(key); if (value !== null) { urlState[key] = value; hasUrlParams = true; } }); if (hasUrlParams) { setState(prev => ({ ...prev, ...urlState })); } }, []); // eslint-disable-line react-hooks/exhaustive-deps // Update URL when state changes const updateUrl = useCallback((newState) => { const params = new URLSearchParams(); keys.forEach(key => { const value = newState[key]; if (value && value !== defaultState[key]) { params.set(key, value); } }); setSearchParams(params, { replace: true }); }, [keys, defaultState, setSearchParams]); // Wrap setState to also update URL const setStateWithUrl = useCallback((updater) => { setState(prev => { const newState = typeof updater === 'function' ? updater(prev) : updater; updateUrl(newState); return newState; }); }, [setState, updateUrl]); return setStateWithUrl; } export default useUrlState;