Skip to content

Instantly share code, notes, and snippets.

@ZacharyL2
Created March 26, 2023 14:06
Show Gist options
  • Save ZacharyL2/417d90c9c3b572498cf049f6dc3315af to your computer and use it in GitHub Desktop.
Save ZacharyL2/417d90c9c3b572498cf049f6dc3315af to your computer and use it in GitHub Desktop.
Simple useUrlState
import { useMemo, useRef } from 'react';
import { useLocation, useNavigate } from 'react-router';
const useUrlState = <S extends Record<string, string>>(
initialState: S,
navigateMode: 'push' | 'replace' = 'push',
) => {
const location = useLocation();
const navigate = useNavigate();
const queryFromUrl = useMemo(() => {
const searchParams = new URLSearchParams(location.search);
return Object.fromEntries(searchParams.entries());
}, [location.search]);
const initialStateRef = useRef(initialState);
const state: S = useMemo(
() => ({
...initialStateRef.current,
...queryFromUrl,
}),
[queryFromUrl],
);
const setState = (s: React.SetStateAction<S>) => {
const newQuery = typeof s === 'function' ? s(state) : s;
const searchParams = new URLSearchParams(location.search);
for (const [k, v] of Object.entries(newQuery)) {
searchParams.set(k, v);
}
navigate(
{
hash: location.hash,
search: searchParams.toString(),
},
{
replace: navigateMode === 'replace',
state: location.state,
},
);
};
return [state, setState] as const;
};
export default useUrlState;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment