Created
November 19, 2019 08:30
-
-
Save billyct/084325c0d8df0e57129bc7bd5a05e8c5 to your computer and use it in GitHub Desktop.
wouter hash-based routing hook
This file contains hidden or 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 { useEffect, useRef, useState, useCallback } from "wouter/react-deps"; | |
export default () => { | |
const [path, update] = useState(currentPathname()); | |
const prevPath = useRef(path); | |
useEffect(() => { | |
// this function checks if the location has been changed since the | |
// last render and updates the state only when needed. | |
// unfortunately, we can't rely on `path` value here, since it can be stale, | |
// that's why we store the last pathname in a ref. | |
const checkForUpdates = () => { | |
const pathname = currentPathname(); | |
prevPath.current !== pathname && update((prevPath.current = pathname)); | |
}; | |
const events = ["replaceHash"]; | |
events.map(e => addEventListener(e, checkForUpdates)); | |
// it's possible that an update has occurred between render and the effect handler, | |
// so we run additional check on mount to catch these updates. Based on: | |
// https://gist.github.com/bvaughn/e25397f70e8c65b0ae0d7c90b731b189 | |
checkForUpdates(); | |
return () => events.map(e => removeEventListener(e, checkForUpdates)); | |
}, []); | |
// the 2nd argument of the `useLocation` return value is a function | |
// that allows to perform a navigation. | |
// | |
// the function reference should stay the same between re-renders, so that | |
// it can be passed down as an element prop without any performance concerns. | |
const navigate = useCallback( | |
to => { | |
location.hash = to; | |
dispatchEvent(new Event('replaceHash')); | |
}, | |
[] | |
); | |
return [path, navigate]; | |
}; | |
const currentPathname = () => location.hash.replace('#', ''); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment