Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question about function combineReducers with multiple reducer module imports #609

Closed
genert opened this issue Aug 23, 2015 · 9 comments
Closed
Labels

Comments

@genert
Copy link

genert commented Aug 23, 2015

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!

@gaearon
Copy link
Contributor

gaearon commented Aug 23, 2015

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

@genert
Copy link
Author

genert commented Aug 23, 2015

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

@gaearon
Copy link
Contributor

gaearon commented Aug 23, 2015

@TheDeveloperXYZ

We're actually going to remove import * from documentation and just show vanilla examples because it confuses a lot of people. See #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. :-)

@gertig
Copy link

gertig commented Sep 27, 2015

@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.

@PavelGriza
Copy link

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.

@gaearon
Copy link
Contributor

gaearon commented May 4, 2016

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!

@PavelGriza
Copy link

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

@gaearon
Copy link
Contributor

gaearon commented May 4, 2016

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.

@craigcosmo
Copy link

craigcosmo commented Sep 20, 2016

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.

@reduxjs reduxjs deleted a comment from jdflaugergues Jan 29, 2018
@reduxjs reduxjs locked as resolved and limited conversation to collaborators Jan 29, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

5 participants