Skip to content

Instantly share code, notes, and snippets.

@jbraithwaite
Forked from gaelollivier/ControlledRouter.js
Last active October 19, 2016 01:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jbraithwaite/4c4ecfbc8a09d63e83d86c6810e0ec77 to your computer and use it in GitHub Desktop.
Save jbraithwaite/4c4ecfbc8a09d63e83d86c6810e0ec77 to your computer and use it in GitHub Desktop.
React Router v4 ControlledRouter
// 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;
@jbraithwaite
Copy link
Author

Remove the setTimeout which was causing bugs

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