Skip to content

Instantly share code, notes, and snippets.

@tim-field
Last active June 23, 2023 01:20
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save tim-field/99104278abfad1b8dd94d26717335963 to your computer and use it in GitHub Desktop.
Save tim-field/99104278abfad1b8dd94d26717335963 to your computer and use it in GitHub Desktop.
Hooks Router
import { useEffect, useState } from "react"
import { createBrowserHistory } from "history"
const history = createBrowserHistory()
const toLocation = path => new URL(path, window.location.href)
// without this react won't re-render as location is the same object
// @see https://reactjs.org/docs/hooks-reference.html#bailing-out-of-a-state-update
const cloneLocation = () => Object.assign({}, window.location)
function useRouter(initial = "") {
const [location, setLocation] = useState(
initial ? toLocation(initial) : cloneLocation()
)
const setRoute = path => {
setLocation(toLocation(path))
}
useEffect(() => {
const { pathname, search } = location
if (window.location.pathname !== pathname) {
history.push(pathname)
setLocation(cloneLocation())
} else if (window.location.search !== search) {
history.replace(pathname + search)
}
}, [location])
useEffect(() => {
window.onpopstate = function historyChange(ev) {
if (ev.type === "popstate") {
setLocation(cloneLocation())
}
}
}, [])
return [location, setRoute]
}
export default useRouter
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment