react-redux-starter-kit
react-redux-starter-kit copied to clipboard
Integrating react-router-scroll
I'm trying to integrate react-router-scroll in a project to fix an issue where react-router won't scroll to the top after a route change. The currently proposed solution is to use react-router-scroll. I was able to get it working but I wanted to double-check that I was doing it correctly and to leave a note for anyone who comes after me trying to do the same thing.
What is the correct way to implement middleware in react-router using the react-redux-starter-kit?
I made changes in two files.
Compare to src/main.js
// ... router-specific snippets from main.js
import createBrowserHistory from 'history/lib/createBrowserHistory'
import { applyRouterMiddleware, useRouterHistory } from 'react-router' // <-- need to import applyRouterMiddleware
import { syncHistoryWithStore } from 'react-router-redux'
import useScroll from 'react-router-scroll' // <-- import the scrolling middleware
// ...
let render = (routerKey = null) => {
const routes = require('./routes/index').default(store)
ReactDOM.render(
<AppContainer
store={store}
history={history}
routes={routes}
routerKey={routerKey}
{/* apply the scroll middleware to the router */}
render={applyRouterMiddleware(useScroll())}
/>,
MOUNT_NODE
)
}
// ...
Compare to src/containers/AppContainer.js
import React, { PropTypes } from 'react'
import { Router } from 'react-router'
import { Provider } from 'react-redux'
class AppContainer extends React.Component {
static propTypes = {
history: PropTypes.object.isRequired,
routes: PropTypes.object.isRequired,
routerKey: PropTypes.number,
render: PropTypes.func, // <-- allow middleware to be injected
store: PropTypes.object.isRequired
}
render () {
const { history, routes, routerKey, render, store } = this.props
return (
<Provider store={store}>
<div style={{ height: '100%' }}>
{/* notice the `render={render}` for injecting middleware into the router */}
<Router history={history} children={routes} key={routerKey} render={render} />
</div>
</Provider>
)
}
}
export default AppContainer
My solution is this
import withScroll from 'scroll-behavior';
// ========================================================
// Browser History Setup
// ========================================================
const browserHistory = withScroll(useRouterHistory(createBrowserHistory)({ //use withScroll
basename: __BASENAME__
}))
I've tried both examples, and:
scroll-behavior works better than react-router-scroll, although it should be the same.
Probably implementation is missing something, since it will scroll even on Back button, which is not the case with scroll-behavior.
Anyway answer to
What is the correct way to implement middleware in react-router using the react-redux-starter-kit?
would be nice.
The starter-kit has changed slightly since I last implemented react-router-scroll. The implementation is simplified slightly because the starter-kit doesn't use react-router-redux anymore.
See src/main.js
// ...
import { applyRouterMiddleware } from 'react-router'
import { useScroll } from 'react-router-scroll'
// ...
let render = () => {
const routes = require('./routes/index').default(store)
ReactDOM.render(
<AppContainer
store={store}
routes={routes}
render={applyRouterMiddleware(useScroll())} {/* <-- apply scroll middleware using a new "render" prop */}
/>,
MOUNT_NODE
)
}
See src/containers/AppContainer.js
// ...
class AppContainer extends Component {
// ...
render () {
const { routes, store, render } = this.props // <-- pull render from props
return (
<Provider store={store}>
<div style={{ height: '100%' }}>
<Router history={browserHistory} children={routes} render={render} /> {/* <-- add scroll middleware to router using render */}
</div>
</Provider>
)
}
}