Skip to content

Instantly share code, notes, and snippets.

@lenkan
Created March 2, 2019 18:26
Show Gist options
  • Star 25 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save lenkan/357b006dd31a8c78f659430467369ea7 to your computer and use it in GitHub Desktop.
Save lenkan/357b006dd31a8c78f659430467369ea7 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
}
}
@salmin89
Copy link

This is great, Thanks!

@paulmelnikow
Copy link

Hi! Does this have a license?

@lenkan
Copy link
Author

lenkan commented Apr 1, 2020

Hi @paulmelnikow. No it does not.

@paulmelnikow
Copy link

Do you mean that it's in the public domain?

@chmartinez
Copy link

You should makes this an npm package! Thanks!

@f-bog
Copy link

f-bog commented Nov 16, 2023

Using this with preact, some really awesome stuff. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment