Skip to content

Instantly share code, notes, and snippets.

@brigand
Last active March 26, 2019 18:32
Show Gist options
  • Save brigand/ea726f15f56b736077cff8f9df7928ff to your computer and use it in GitHub Desktop.
Save brigand/ea726f15f56b736077cff8f9df7928ff to your computer and use it in GitHub Desktop.
The `useLocationState` hook gives a `React.useState`-like interface to updating the HTML5 History API location state.
function Foo() {
const [count, setCount] = useLocationState('Foo', 0);
return (
<div>
<button onClick={() => setCount(c => c + 1)}>Clicks: {count}</button>
<button onClick={() => setCount(0)}>Reset</button>
</div>
);
}
import * as React from 'react';
import { createBrowserHistory } from 'history';
const history = createBrowserHistory();
export function useHistory() {
return history;
}
export function useLocationState<T>(
key: ?string,
initial: T,
): [T, (update: T | ((x: T) => T)) => void] {
const stateKey = key || '_default';
const [loc, setLoc] = React.useState({
pathname: window.location.pathname,
search: window.location.search,
hash: window.location.hash,
state: window.history.state && window.history.state.state,
});
const get = () => {
if (loc.state && loc.state[stateKey] !== undefined) {
return loc.state[stateKey];
}
return initial;
};
React.useEffect(
() =>
history.listen((location) => {
setLoc(location);
}),
[],
);
const set = React.useCallback(
(update, callback) => {
const state = typeof update === 'function' ? update(get()) : update;
history.replace({
...loc,
state: {
...loc.state,
[stateKey]: state,
},
});
},
[loc],
);
return [get(), set];
}
export default history;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment