Created
March 26, 2023 14:06
-
-
Save ZacharyL2/417d90c9c3b572498cf049f6dc3315af to your computer and use it in GitHub Desktop.
Simple useUrlState
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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