The state in a redux / response application has a property called a reducer

I am building an application using Redux and React. I ran into a problem when I cannot match state properties with components, because state has a property that matches the name of the reducer used.

Abbreviations are created using the combineReducers method

 const rootReducer = combineReducers({ appReducer }) 

Initial state

 const initialState = { sources: [], left: {}, right: {}, diff: {} } 

However, in the mapStateToProps component function:

 function mapStateToProps(state) { return { sources: state.sources } } 

state.sources - undefined because the value of state is

 { appReducer: { sources: [], left: {}, right: {}, diff: {} } } 

Is this a sign of contraction? So when I use more reducers, will they all add a new property to the state variable? Or something is wrong on my part (I have never noticed this behavior in reduction textbooks).

thanks

+7
javascript reactjs state redux
source share
2 answers

If you have only one reducer, you do not need to combineReducers() . Just use it directly:

 const initialState = { sources: [], left: {}, right: {} } function app(state = initialState, action) { switch (action.type) { case 'ADD_SOURCE': return Object.assign({}, state, { sources: [...state.sources, action.newSource] }) case 'ADD_SOURCE_TO_LEFT': return Object.assign({}, state, { left: Object.assign({}, state.left, { [action.sourceId]: true }) }) case 'ADD_SOURCE_TO_RIGHT': return Object.assign({}, state, { right: Object.assign({}, state.right, { [action.sourceId]: true }) }) default: return state } } 

Now you can create a store with this gear:

 import { createStore } from 'redux' const store = createStore(app) 

And connect the component to it:

 const mapStateToProps = (state) => ({ sources: state.sources }) 

However, your gearbox is hard to read because it updates several different things at once. Now this is the moment when you want to split it into several independent gearboxes:

 function sources(state = [], action) { switch (action.type) { case 'ADD_SOURCE': return [...state.sources, action.newSource] default: return state } } function left(state = {}, action) { switch (action.type) { case 'ADD_SOURCE_TO_LEFT': return Object.assign({}, state, { [action.sourceId]: true }) default: return state } } function right(state = {}, action) { switch (action.type) { case 'ADD_SOURCE_TO_RIGHT': return Object.assign({}, state, { [action.sourceId]: true }) default: return state } } function app(state = {}, action) { return { sources: sources(state.sources, action), left: left(state.left, action), right: right(state.right, action), } } 

This is easier to maintain and understand, and also makes it easy to modify and test gearboxes independently.

Finally, as a last step, we can use combineReducers() to generate the root reducer app instead of writing it manually:

 // function app(state = {}, action) { // return { // sources: sources(state.sources, action), // left: left(state.left, action), // right: right(state.right, action), // } // } import { combineReducers } from 'redux' const app = combineReducers({ sources, left, right }) 

There is not much benefit from using combineReducers() instead of writing the root reducer manually, except that it is a little more efficient and is likely to save you a few typos. In addition, you can apply this template several times in your application: its subtlety for combining unconnected gearboxes into one gearbox several times in a nested manner.

All this refactoring will not affect the components.

I suggest you look at my free Egghead course on Redux , which covers this reduction composition pattern and shows how combineReducers() implemented.

+17
source share

Actually, I believe that your initial state would be as follows:

 { appReducer: { sources: [], left: {}, right: {}, diff: {} } } 

This is because combineReducers works by taking the name of the reducer and matching its contents with that name.

It’s also just a note, but if you intend to use more than one gearbox, the names of your gearboxes should be more specific than appReducer , and (just my personal opinion) they don’t need the word reducer . A typical application might look like this:

 combineReducers({ user: userReducer, messages: messagesReducer, notifications: notificationsReducer }); 

Then your status can be obtained, for example:

 state.user.email state.messages[0] 
+5
source share

All Articles