-
-
Save jbraithwaite/4c4ecfbc8a09d63e83d86c6810e0ec77 to your computer and use it in GitHub Desktop.
React Router v4 ControlledRouter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Code taken from: | |
// https://gist.github.com/gaelduplessix/050e5cce31f9fabb1030f4ba47663db5 | |
// gaelduplessix/ControlledRouter.js | |
import React, { Component } from 'react' | |
import BrowserHistory from 'react-history/BrowserHistory' | |
import { Push } from 'react-history' | |
import { StaticRouter } from 'react-router' | |
class RouterWrapper extends Component { | |
componentWillReceiveProps(nextProps) { | |
const { setLocation, historyLocation, update } = nextProps; | |
if (update){ | |
setLocation(historyLocation); | |
} | |
} | |
render() { | |
return this.props.children | |
} | |
} | |
/** | |
* ControlledRouter, greatly inspired by https://gist.github.com/donnanicolas/3d76397a92551f449637590bf0413133 | |
* Usage: | |
* <ControlledRouter location={location} setLocation={setLocation}> | |
* <App /> | |
* </ControlledRouter> | |
*/ | |
class ControlledRouter extends Component { | |
constructor(props) { | |
super(props) | |
this.prevPathname = '' | |
} | |
shouldComponentUpdate(nextProps, nextState) { | |
return nextProps.location.pathname !== this.props.location.pathname; | |
} | |
componentDidUpdate() { | |
// Scroll to the top left on page changes | |
if (window && window.scrollY) { | |
window.scroll(0, 0); | |
} | |
} | |
render() { | |
const { location, setLocation, children } = this.props | |
return ( | |
<BrowserHistory> | |
{({ history, action, location: historyLocation }) => { | |
const historyPathname = historyLocation.pathname | |
const controlledPathname = location.pathname | |
const pathChanged = historyPathname !== controlledPathname | |
const shouldUpdateState = pathChanged && historyPathname !== this.prevPathname | |
const shouldUpdateHistory = pathChanged && !shouldUpdateState | |
// Keep track of previous pathname | |
this.prevPathname = historyLocation.pathname | |
return ( | |
<RouterWrapper setLocation={setLocation} historyLocation={historyLocation} update={shouldUpdateState}> | |
<StaticRouter | |
action={action} | |
location={historyLocation} | |
onPush={history.push} | |
onReplace={history.replace} | |
blockTransitions={history.block} | |
> | |
{ shouldUpdateHistory ? <Push path={location.pathname} /> : children } | |
</StaticRouter> | |
</RouterWrapper> | |
); | |
}} | |
</BrowserHistory> | |
) | |
} | |
} | |
ControlledRouter.displayName = 'ControlledRouter' | |
export default ControlledRouter; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Remove the setTimeout which was causing bugs