Skip to content

Instantly share code, notes, and snippets.

@danydodson
Last active November 15, 2022 05:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danydodson/9d682ded2c010816dc19d40553fbc0e1 to your computer and use it in GitHub Desktop.
Save danydodson/9d682ded2c010816dc19d40553fbc0e1 to your computer and use it in GitHub Desktop.
react hooks
/**
* @info React hook that keeps up to date with the current location.
*/
import { useState, useEffect } from 'react'
function getCurrentLocation() {
return {
pathname: window.location.pathname,
search: window.location.search
}
}
/**
* @type {Array<() => void>}
*/
const listeners = []
/**
* Notifies all location listeners.
* Can be used if the history state has been manipulated in by another module.
* Effectifely, all components using the 'useLocation' hook will update.
*/
export function notify() {
listeners.forEach(listener => listener())
}
export function useLocation() {
const [{ pathname, search }, setLocation] = useState(getCurrentLocation())
useEffect(() => {
window.addEventListener('popstate', handleChange)
return () => window.removeEventListener('popstate', handleChange)
}, [])
useEffect(() => {
listeners.push(handleChange)
return () => listeners.splice(listeners.indexOf(handleChange), 1)
}, [])
function handleChange() {
setLocation(getCurrentLocation())
}
/**
* @param {string} url
*/
function push(url) {
window.history.pushState(null, null, url)
notify()
}
/**
* @param {string} url
*/
function replace(url) {
window.history.replaceState(null, null, url)
notify()
}
return {
push,
replace,
pathname,
search
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment