Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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

This comment has been minimized.

Copy link
Owner Author

commented Oct 6, 2016

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
You can’t perform that action at this time.