Skip to content

Instantly share code, notes, and snippets.

@mminer
Created August 23, 2018 18:25
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 mminer/ad4e8cc8e5f272a180219ce69b0abecb to your computer and use it in GitHub Desktop.
Save mminer/ad4e8cc8e5f272a180219ce69b0abecb to your computer and use it in GitHub Desktop.
React higher-order component that provides basic hash-based routing.
// Usage:
//
// const YourComponent = ({ activePageHash }) => ...
// export default withHashRouter(YourComponent, ['#valid-page-1', '#valid-page-2']);
import { Component, createElement as h } from 'react';
// Falls back to the initial page if the hash specifies an unknown one.
function replaceHashWithValidPage(validPageHashes) {
if (!validPageHashes) {
return;
}
const { hash, pathname } = location;
if (validPageHashes.includes(hash)) {
return;
}
// Changing location.hash directly causes onhashchange to fire, which is
// undesirable when calling this function from our hashchange handler.
history.replaceState(null, null, pathname + validPageHashes[0]);
}
export default function withHashRouter(WrappedComponent, validPageHashes) {
return class HashRouter extends Component {
constructor(props) {
super(props);
replaceHashWithValidPage(validPageHashes);
this.handleHashChange = this.handleHashChange.bind(this);
this.state = { activePageHash: location.hash };
}
componentDidMount() {
window.addEventListener('hashchange', this.handleHashChange);
}
componentWillUnmount() {
window.removeEventListener('hashchange', this.handleHashChange);
}
render() {
return h(WrappedComponent, {
activePageHash: this.state.activePageHash,
});
}
handleHashChange() {
replaceHashWithValidPage(validPageHashes);
if (location.hash === this.state.activePageHash) {
return;
}
this.setState({ activePageHash: location.hash });
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment