Search code examples
javascriptreactjsreduximmutable.jsreact-router-redux

React Router Redux Immutable


Been using this boilerplate for a while and have been using plain JS objects as the store/state up until I started getting some odd mutations randomly so decided to switch to Immutable.js. Currently I'm trying to implement redux-immutable into my code. I'm having some issue with react-router-redux and redux-immutable; unfortunately I don't know these libraries very well 'under-the-hood' so having a lot of trouble debugging this. I have followed the instructions in the redux-immutable README on this.

Getting this error in my index.js file.

Uncaught TypeError: Cannot read property 'toJS' of undefined

index.js

const initialState = Immutable.Map({});

const store = configureStore(initialState);
const history = syncHistoryWithStore(hashHistory, store, {
  selectLocationState (state) {
    return state.getIn([
      'route',
      'location'
    ]).toJS();
  }
});

render(
  <Provider store={store}>
    <Router history={history} routes={routes} />
  </Provider>,
  document.getElementById('root')
);

configureStore.js

const router = routerMiddleware(hashHistory);

const enhancer = compose(
  applyMiddleware(thunk, router, logger),
  DevTools.instrument(),
  persistState(
    window.location.href.match(
      /[?&]debug_session=([^&]+)\b/
    )
  )
);

export default function configureStore(initialState) {
  const store = createStore(rootReducer, initialState, enhancer);

  if (module.hot) {
    module.hot.accept('../reducers', () =>
      store.replaceReducer(require('../reducers'))
    );
  }

  return store;
}

rootReducer.js

import {combineReducers} from 'redux-immutable';

import routing from './Routing';
import Graphing from './Graphing';
import Syncing from './Syncing';
import Navigating from './Navigating';
import Notifying from './Notifying';

const rootReducer = combineReducers({
  routing,
  Graphing,
  Navigating,
  Syncing,
  Notifying
});

export default rootReducer;

routing.js (routing reducer)

import {LOCATION_CHANGE} from 'react-router-redux';

const initialState = Immutable.fromJS({
  location: {}
});

export default (state = initialState, action) => {
  if (action.type === LOCATION_CHANGE) {
    return state.merge({
      location: action.payload
    });
  }

  return state;
};

Solution

  • As per the documentation it's suggested to use routing as the reducer key. So here you are basically trying to access the store with the key routing instead of route

    I just tried it without immutable, and is as below,

    const history = syncHistoryWithStore(browserHistory, store, {
      selectLocationState(state) {
        console.log(state.routing.locationBeforeTransitions);
        return state.routing;
      }
    });
    

    This will return, enter image description here

    Hope it helps