This is the fifth part in a series on Redux, a state Management Framework used with single page application frameworks such as React and Angular. This series looks at using Redux without another framework. Please read part 1, Part 2. and Part 3, and part 4 before reading this.

I write a lot more about Redux and Angular in the bonus book to the Angular 6 series.

Review the Reducer

This is the reducer we had in the previous samples:

view plain print about
1function reducer(state = initialState, action) {
2 var newState = Object.assign({}, state)
3
4 switch (action.type) {
5 case 'NAME_MODIFIED':
6 newState.helloUser = action.value
7 break;
8 case 'NAME_LEFT':
9 newState.goodbyeUser = action.value;
10 newState.helloUser = '';
11 break;
12 default:
13 // do nothing
14 }
15 return newState;
16 }

It is functional, but over time as your application grows will become unwieldy. Each aspect of state is better handled separately with it's own actions and state modifications. To do that, we separate a single reducer into multiple reducers.

Split the Reducer

This example expands on the previous example, to show you how to split a single reducer into multiple reducers.

State objects and Reducers can get very complex in a real-world application. What do we do to make them simpler? What we're going to do is create a reducer for each section of the site and then combine them into our one big reducer function.

Let's start by creating a reducer for the hello portion of this app:

view plain print about
1function helloUser(state = '', action){
2 var newState = state;
3 switch (action.type) {
4 case 'NAME_MODIFIED':
5 newState = action.value;
6 break;
7 case 'NAME_LEFT':
8 newState = '';
9 break;
10 default:
11 }
12 return newState
13}

I created a new function named helloUser(). Notice that this function is named the same name as the state property. This is done on purpose, and you'll find out why in the next article. This function has a similar signature to the reducer. It accepts a state and an action. However, it does not accept the full state object. We'll send in the specific value for the helloUser state, which is just one branch of the main state object. This reducer function only focuses on handling its own state, not other states.

The helloUser() reducer only operates on the helloUser state variable. Notice it defaults the newState to an empty string in the command line signature. We might do something more complex if we were using an object or other data type. This reducer has to handle both major actions. If the name is modified, it sets to the new name. If we said goodbye to the user, then the helloUser resets to an empty string.

Create a goodbyeUser() reducer:

view plain print about
1function goodbyeUser(state = '', action){
2 var newState = state;
3 switch (action.type) {
4 case 'NAME_LEFT':
5 newState = action.value;
6 break;
7 default:
8
9 }
10 return newState
11}

This reducer only needs to operate on the goodbyUser state. As with the helloUser reducer, and as such only needs to respond to the NAME_LEFT action. In that case, it takes the value from the action and sets it to the new state. The NAME_MODIFIED state is ignored here.

Now, create the actual reducer:

view plain print about
1function reducer(state = initialState, action) {
2 return {
3 helloUser: helloUser(state.helloUser, action),
4 goodbyeUser: goodbyeUser(state.goodbyeUser, action)
5 }
6}

This automatically returns an object, representing the new state. The helloUser property is given the results of the helloUser() reducer. The goodbyeUser property is given the results of the goodbyeUser() reducer.

Run the app and you'll see it working.