Skip to content

Latest commit

 

History

History
65 lines (46 loc) · 3.08 KB

2-combining-reducers.litcoffee

File metadata and controls

65 lines (46 loc) · 3.08 KB

2. Combining Reducers

Redux is more of a paradigm than a library. The library consists of just a few helper functions to make this paradigm easier to implement.

One of the first things you might notice about reducers is that the functionality of a real-life application will not be satisfied by the simplistic functions we've seen so far. Perhaps we could define one monolithic reducer function, but that would easily become a tangled nest of code. We need some way to combine reducers. The aptly named combineReducers helper will help us.

First import the function from Redux:

{combineReducers} = require 'redux'

We will borrow two reducers from the last segment, with one important distinction: the state argument defines a default value. For the counter reducer the initial state is 0, for the user reducer {}. The reasoning behind this is to ensure each part of the combined state is valid.

counter_reducer = (state=0, action) ->
    amount = action.amount
    amount = 1 if not amount?
    switch action.type
        when 'inc'
            return state + amount
        when 'dec'
            return state - amount
    return state # Fallback

user_reducer = (state={}, action) ->
    if action.type == 'set'
        return Object.assign {}, state, action.values
    return state # Fallback

To combine the reducers into a combined_reducer, we call combineReducers. Surprised? The argument to this helper function defines the shape of the final combined state, an object with the keys we set here, and the values output by our reducers.

combined_reducer = combineReducers {
    counter: counter_reducer
    user: user_reducer
}

When we define the initial state it should satisfy the nested shape defined by the combineReducers argument:

state = {
    counter: 1
    user: {
        name: "Josh"
        username: "itsmejosh"
        age: 22
    }
}

console.log 'initial state =', state
# initial state = { counter: 1,
#   user: { name: 'Josh', username: 'itsmejosh', age: 22 } }

And as usual we call the reducer with a state and an action to get an updated state:

state = combined_reducer(state, {type: 'inc'})
state = combined_reducer(state, {type: 'set', values: {username: 'omgimjosh'}})

console.log 'state =', state
# state = { counter: 2,
#   user: { name: 'Josh', username: 'omgimjosh', age: 22 } }

What happens when we run this combined reducer is the action is passed through every reducer. This means we could do some tricky things with actions that match multiple reducers, but more likely means we should be careful with the names of our actions. Overly simple names like inc and set will easily collide as the application becomes more complex. We'll look at ways to avoid this, while avoiding some boilerplate of common reducer actions, in an upcoming episode.

But first we'll look into creating a reducer for the most common shape of web application data: a collection of items.


Next: Building a Collection Reducer