Skip to content

Instantly share code, notes, and snippets.

@lenkan
Created March 2, 2019 18:26
Show Gist options
  • Save lenkan/29a9ac903720ee03bc769dda8955a52b to your computer and use it in GitHub Desktop.
Save lenkan/29a9ac903720ee03bc769dda8955a52b to your computer and use it in GitHub Desktop.
React hook that keeps up to date with the current location.
// @ts-check
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