dvdzkwsk / react-redux-starter-kit

Get started with React, Redux, and React-Router.
MIT License
10.29k stars 2.2k forks source link

Integrating react-router-scroll #849

Open heygrady opened 8 years ago

heygrady commented 8 years ago

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
janjon commented 8 years ago

My solution is this

import withScroll from 'scroll-behavior';

// ========================================================
// Browser History Setup
// ========================================================
const browserHistory = withScroll(useRouterHistory(createBrowserHistory)({  //use withScroll
  basename: __BASENAME__
}))
easingthemes commented 8 years ago

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.

heygrady commented 7 years ago

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>
    )
  }
}