syncHistoryWithStore example for using enhancers with middleware? #305

Closed
tanepiper opened this Issue Feb 24, 2016 · 6 comments

Projects

None yet

4 participants

@tanepiper

Consider the following example:

import thunk from 'redux-thunk';
import {
  applyMiddleware,
  compose,
  createStore
} from 'redux';
import { browserHistory } from 'react-router';
import { syncHistory } from 'react-router-redux';

import { reducers } from './../reducers';

/**
 * Method to create stores based on a set of passed
 * reducers
 * @returns {*}
 */
export function configureStore(initialState = {}) {

  const reduxRouterMiddleware = syncHistory(browserHistory);

  const enhancer = compose(
    // Middleware you want to use in development:
    applyMiddleware(thunk, reduxRouterMiddleware),
    // Required! Enable Redux DevTools with the monitors you chose
    window.devToolsExtension ? window.devToolsExtension() : f => f
  );

  // Sync dispatched route actions to the history

  const store = createStore(reducers, initialState, enhancer);

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

With the 4.0.0 API, syncHistoryWithStore now needs the store to be created first, but in this case the enhancer needs to be created before the store, which needs the middleware created from 3.x.x syncHistory method.

What would be the best way to upgrade this?

@timdorr
Member
timdorr commented Feb 24, 2016

Just add a history arg to your configureStore function.

export function configureStore(history, initialState = {}) {

  const enhancer = compose(
    // Middleware you want to use in development:
    applyMiddleware(
      thunk,
      routerMiddleware(history)
    ),
    // Required! Enable Redux DevTools with the monitors you chose
    window.devToolsExtension ? window.devToolsExtension() : f => f
  );

  // Sync dispatched route actions to the history

  const store = createStore(reducers, initialState, enhancer);

  if (module.hot) {
    module.hot.accept('../reducers', () => {
      store.replaceReducer(require('./../reducers').default);
    });
  }
  return store;
}
@timdorr timdorr closed this Feb 24, 2016
@tanepiper

@timdorr Hmm, tried that but I get the following:

Uncaught Error: Expected the routing state to be available either as 'state.routing' or as the custom expression you can specify as 'selectLocationState' in the 'syncHistoryWithStore()' options. Ensure you have added the 'routerReducer' to your store's reducers via 'combineReducers' or whatever method you use to isolate your reducers.

I'm not doing anything fancy with Immutable states here, this was just working in 3.x based on pretty standard React/Redux setup.

I've tried it with what you've suggested, this is the index.js of the app is this:

import 'babel-polyfill';

import React from 'react';
import ReactDOM from 'react-dom';
import { browserHistory } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';

import Root from './containers/Root';
import configureStore from './store/configureStore';

const store = configureStore(browserHistory);
const history = syncHistoryWithStore(browserHistory, store);

// Custom history listener to do a redirect from a #/hash path
history.listen((location) => {
  const path = (/#(\/.*)$/.exec(location.hash) || [])[1];
  if (path) history.replace(path);
});

const rootElem = document.getElementById('root');
const rootNode = (<Root history={history} store={store} />);

ReactDOM.render(rootNode, rootElem);

The createStore method is essentially the same as you have above. In reducers/index.js we have:

import { combineReducers } from 'redux';
import { routeReducer } from 'react-router-redux';

import {....}  // Other reducers in the app

export const reducers = combineReducers({
  ...  // other reducers
  routing: routeReducer
});
@tanepiper

Never mind, fixed in the end

@txm
txm commented Mar 1, 2016

How did you fix it? I have the same since updating all packages in package.json

@txm
txm commented Mar 1, 2016

bah s%routeReducer%routerReducer%

@sirichaij

I found it. 'routeReducer' has been changed to 'routerReducer'

import { routerReducer } from 'react-router-redux';
export const reducers = combineReducers({
  ...  // other reducers
  routing: routerReducer
});
@rcsole rcsole referenced this issue in xing/hops Apr 26, 2016
Closed

ES6 Modules #28

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment