How we Redux — Part 4 (Reducers and Stores)

Today we are going to integrate Redux: Reducers and Stores into our Meteor app. You can find Part 3 of this series here.

Reducers

In Redux, Actions signal to the user-interface that something happened. Actions are stateless and highly predictable. Actions describe the type of state change performed but don’t dictate how state changes. In Redux, the logic for state changes is done through Reducers.

So remember how we were talking about Domain State vs UI State in Part 1? As opposed to storing Domain State in different database collections, we store UI state in a single object. This idea comes from the Elm Architecture and the Om library which is the way to build user interfaces via React in ClojureScript.

For our Todo app, it’s very simple. The best way to make your first reducer is to code it. Let’s do it.

First we need to spec out our UI State. The product manager for Todos Corp wants you to be able to filter the Todos. Either you can see all of them, only the completed ones, and the ones that aren’t completed. We also want to paginate the list of Todos, 10 Todos per page.

Let’s map this single object:

{
visibilityFilter: 'SHOW_ALL',
pageSkip: 0
}

We have a value for the state of the visibilityFilter, this will be the state of what Todos we want the user to see. The interesting one is the pageSkip. This is intended to store the current “skip” value which we will feed to our Domain State to “paginate” its results. Our UI state change will be triggered by a ReactPaginate component and the pageSkip state will increment by 10. More on that in the next part.

Okay so Reducers describe changes to the UI state, so we need to provide 2 descriptions one for each key of our single object.

Given the same arguments, it should calculate the next state and return it. No surprises. No side effects. No API calls. No mutations. Just a calculation.

As you can see our functions take in arguments: state and action. Our UI is going to dispatch an Action, the Action will the Reducer and be processed according to the action.type

Note, these functions are pure. We are returning a new state from our reducers with every action.

The resulting reducer calls every child reducer, and gather their results into a single state object. The shape of the state object matches the keys of the passed reducers.

Root Reducer

So we have two reducers but in Redux, your state is a single object. We need to utilize Reducer Composition to make our code modular. This way we can write separate functions representing the state changes for “slices” of our single object. There’s a cool utility method for doing this called combineReducers. This function returns an object whose values are the different functions we will write to explain how our UI state changes.

Okay now that we have the Reducers taken care of, let’s go make a Store.

Stores

Alright, we made some Actions. Check. We made some Reducers. Check. What are we forgetting? Oh. Yeah! The Store! How could I forget about the Store!

The Store, in Redux, does many things. And we can ONLY HAVE ONE. Remember that. It has 3 methods:

// A Redux Store has 3 methods
// we'll review this syntax shortly
const store = createStore(reducer);
1. store.getState() -> returns the current state 
2. store.dispatch({type: 'SAY_HELLO', message: 'HAI'});
// We won't use this really. We other means for reactivity.
3. store.subscribe(someFunction);

When you think of your UI State and how it changes, making a Store and getting started become so much easier! Let’s make a store

Middlewares

In parts 2 and 3 we went over the added tools Redux has for handling different things: logging, crash reporting, talking to an asynchronous API, routing, and more. Middlewares provide extensions to dispatching an action. We need to incorporate these into our Store at creation time.

We’ll be adding two middleware:

We are using the applyMiddleware function to extend our store with thunk and logger.

For a reminder:

Thunk — allows you to write action creators that return a function instead of an action. This is KEY for dispatching DOMAIN STATE.

Logger —

What better what to explain it than this picture

Dispatching Actions

Okay we have Actions, we have Reducers, and now we have a Store. Let’s write some code to dispatch these actions in certain contexts. ALL ACTIONS ARE PROCESSED THROUGH THE STORE. Even side effects.

Conclusion

Great! This concludes Part 4! We went over tons of core Redux principles and I encourage everyone to read the Redux documentation. In the next lesson, we’re going to be connecting React components to all the code we’ve built thus far. The end result? A paginated-todos list with some filters!

If you like this series, recommend it to your friends! Follow me on twitter:@abhiaiyer

Getting into React? Check out my post on JSX here.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.