Redux: Question about function combineReducers with multiple reducer module imports

Created on 23 Aug 2015  ·  9Comments  ·  Source: reduxjs/redux

Hello.

Let's imagine that we have a reducer file like this:

export function something1 (state={}, action) {
  switch (action.type) {
    ...
  }
}

export function something2 (state={}, action) {
  switch (action.type) {
    ...
  }
}

There are also 3 other similar reducer files with multiple exports.

While the document merely gives an example how to use combineReducers with only 1 file with multiple exports - combineReducers | Redux (_import * as reducers from './reducers';_)

Then how do you use that function with multiple imports like this?

import * as reducers1 from './reducer1';
import * as reducers2 from './reducer2';
...

const reducer = combineReducers(???); // What argument to write. How to turn imports to object?

Thanks!

question

Most helpful comment

Imports _are_ object. Just like you'd merge two objects:

import * as reducers1 from './reducer1';
import * as reducers2 from './reducer2';

const allReducers = Object.assign({}, reducers1, reducers2);
const reducer = combineReducers(allReducers);

All 9 comments

Imports _are_ object. Just like you'd merge two objects:

import * as reducers1 from './reducer1';
import * as reducers2 from './reducer2';

const allReducers = Object.assign({}, reducers1, reducers2);
const reducer = combineReducers(allReducers);

Thanks for such fast reply; didn't notice that ES6 has added such function. :+1:
I wonder if adding such thing to redux document would be worthwhile for in case if other would seek that?

@TheDeveloperXYZ

We're actually going to remove import * from documentation and just show vanilla examples because it confuses a lot of people. See https://github.com/rackt/redux/pull/590.

Thanks for such fast reply; didn't notice that ES6 has added such function.

You can use something like Lodash's assign if you don't want to include a polyfill, and already have Lodash or something similar. It's just merging objects; nothing magic. :-)

@gaearon Good idea to remove import *. I'd also recommend at mentioning what destructuring statements and spread operators are in a comment the first time you use them.

Is it possible to multiple call combineReducers?
If I use combineReducers in separate file and then I want to attach one more reducer (actually, it is routerReducer from react-router-redux) is it possible to do?
The main issue that I cannot use spread operator (...reducers, routing: routerReducer) only staged ES6 features.

The main issue that I cannot use spread operator (...reducers, routing: routerReducer) only staged ES6 features.

It just desugars to Object.assign({}, reducers, { routing: routerReducer }). Object.assign() is part of ES6 and you can use a polyfill for it.

You can even write a reasonable approximation by hand:

let finalReducers = {}
Object.keys(reducers).forEach(key => finalReducers[key] = reducers[key])
finalReducers.routing = routerReducer

const reducer = combineReducer(finalReducers)

It’s all just JavaScript!

Thanks for fast response!
I was trying to use Object.assign() declaration before asking this question. In that case before combining I had rootReducer object with property default: function combination() which worked correctly. But after using var reducer = Object.assign({}, rootReducer, { routing: routerReducer }) my variable reducer contained just a property routing: function routerReducer().
After combineReducer(finalReducers) returned a function with routing but without my app reducers.

I guess I was doing something in a wrong way, but I can't understand what exactly.

But thank you very much about your approach with using Object.keys

If you see default means you are importing an ES module with a CommonJS require. This is usually a mistake. Please check out https://medium.com/@kentcdodds/misunderstanding-es6-modules-upgrading-babel-tears-and-a-solution-ad2d5ab93ce0 for some info on this.

If you can publish a project reproducing this I'm happy to take a look.

I do it like this:

mainReducer.js

import {combineReducers} from 'redux'
import {routerReducer} from 'react-router-redux'

// list of reducers
import registerReducer from 'registerReducer'
import homeReducer from 'homeReducer'
import aboutReducer from 'aboutReducer'
import contactUsReducer from 'contactUsReducer'


export const mapStateToProps = (state) => {
    return {
        register: state.register,
        home: state.home,
        about: state.about,
        contact:state.contact
    }
}
export default combineReducers({
    routing: routerReducer,
    register: registerReducer,
    home: homeReducer,
    about: aboutReducer,
    contact: contactUsReducer
})

There is function mapStateToProps in there. The reason is because I often forgot to add entry to mapStateToProps function when it is put in other file. So I bring it to my main reducer,and for easy access. Open multiple files to make action and reducer is real pain.

Was this page helpful?
0 / 5 - 0 ratings