UNPKG

@supunlakmal/hooks

Version:

A collection of reusable React hooks

73 lines 3.62 kB
import { useState, useCallback, useEffect } from 'react'; import { useEventListener } from '../event-handling/useEventListener'; // Helper to safely get query param value (handles SSR) const getQueryParamValue = (paramName) => { if (typeof window === 'undefined' || !window.location || !window.location.search) { return null; } const params = new URLSearchParams(window.location.search); return params.get(paramName); }; // Helper to update query param in URL without adding history entry const updateUrlQueryParam = (paramName, value) => { if (typeof window === 'undefined' || !window.history || !window.location) { return; } const params = new URLSearchParams(window.location.search); if (value === null || value === undefined) { params.delete(paramName); } else { params.set(paramName, value); } const newSearch = params.toString(); // Create new URL preserving path and hash const newUrl = `${window.location.pathname}${newSearch ? '?' + newSearch : ''}${window.location.hash}`; // Use replaceState to avoid polluting browser history window.history.replaceState(window.history.state, '', newUrl); }; /** * Custom hook to synchronize a state variable with a URL query parameter. * Note: This basic version only handles string values. * * @param {string} paramName The name of the URL query parameter. * @param {string} [initialValue=''] The default value to use if the parameter is not in the URL. * @returns {[string, (newValue: string | null) => void]} A tuple containing: * - The current value of the query parameter state. * - A function to update the state and the URL query parameter (pass null to remove). */ export const useQueryParam = (paramName, initialValue = '') => { // State reflects the param value, falling back to initialValue if absent const [value, setValue] = useState(() => { var _a; return (_a = getQueryParamValue(paramName)) !== null && _a !== void 0 ? _a : initialValue; }); // Update state and URL parameter const updateParam = useCallback((newValue) => { // Determine the value to set in state (fallback to initialValue if param is removed) const stateValueToSet = newValue !== null && newValue !== void 0 ? newValue : initialValue; setValue(stateValueToSet); // Update the URL (null removes the parameter) updateUrlQueryParam(paramName, newValue); }, [paramName, initialValue]); // Listen for popstate events (browser back/forward) to update state from URL const handlePopState = useCallback(() => { var _a; setValue((_a = getQueryParamValue(paramName)) !== null && _a !== void 0 ? _a : initialValue); }, [paramName, initialValue]); useEventListener('popstate', handlePopState); // Effect to ensure state is synced if paramName changes or on initial load // (Handles cases where URL might change externally without popstate, though less common) useEffect(() => { const currentValueFromUrl = getQueryParamValue(paramName); if (currentValueFromUrl !== value) { // Only update if different from current state setValue(currentValueFromUrl !== null && currentValueFromUrl !== void 0 ? currentValueFromUrl : initialValue); } // Depend on paramName and initialValue to re-sync if they change }, [paramName, initialValue, value]); // Include value to prevent unnecessary updates if URL matches state return [value, updateParam]; }; //# sourceMappingURL=useQueryParam.js.map