Sign in
Log inSign up

How to use react-router-redux with immutable.js

Yanni Nightingale's photo
Yanni Nightingale
·Aug 28, 2016

1. react-router-redux usage

react-router-redux is library created by React Community using for connecting react-router to redux.

react-router-redux is easy to use. You need first import syncHistoryWithStore and routerReducer these two functions:

import {syncHistoryWithStore, routerReducer} from 'react-router-redux'

Then you have to define a routing property in store:

const store = createStore(
  combineReducers({
    ...reducers,
    routing: routerReducer
  })
)

At last, create a history object, and pass it to Router:

import {Router, Route, browserHistory} from 'react-router'

const history = syncHistoryWithStore(browserHistory, store)

ReactDOM.render(
  <Provider store={store}>
    <Router history={history}>
      <Route path="/" component={App}>
        <Route path="foo" component={Foo}/>
        <Route path="bar" component={Bar}/>
      </Route>
    </Router>
  </Provider>,
  document.getElementById('root')
)

If you need to navigate by redux action:

import {routerMiddleware, push} from 'react-router-redux'

const middleware = routerMiddleware(browserHistory)
const store = createStore(
  reducers,
  applyMiddleware(middleware)
)

function createFooAction() {
    return push('/foo);
}

2. with immutable

In a word, react-router-redux works fine with normal store's state. But if you use immutable.js to wrap state, you have to make some changes.

2.1. Your own custom routerReducer

See origin routerReducer definition. This object spread syntax need state be a pure JavaScript object. But an immutable map is not, so you have to redefine it:

import {Map} from 'immutable'

const routerReducerInitialState = new Map({'locationBeforeTransitions': null});

const immutableRouterReducer = (state = routerReducerInitialState, {type, payload}) => {
    if (type === LOCATION_CHANGE) {
        return state.set('locationBeforeTransitions', payload)
    }

    return state
}

2.2. Your own custom selectLocationState

selectLocationState function is an option of the 3rd parameter of syncHistoryWithStore. The default definition is:

const defaultSelectLocationState = state => state.routing

The key is visiting locationBeforeTransitions in state, so your redefine it:

const history = syncHistoryWithStore(browserHistory, store, {
    selectLocationState: state => ({locationBeforeTransitions: state.routing.get('locationBeforeTransitions')}) 
})

Notice: as combineReducer creates a pure JavaScript object always, the topmost level of state is NOT an immutable object, so you state.routing not state.get('routing').