Using Redux With React

React and Redux are two Javascript libraries that are commonly used together.  There is a common misconception that they come together as part of a package. However, they can each be used separately and stand alone.  That being said, in large scale applications it may make sense to use Redux with React to manage each of your component’s state.  I found that learning the ins and outs of React and Redux took some time to really get a deep understanding as to what is going on.  With the React-Redux library, there is a lot that happens under the hood, so some of it can feel almost like magic.  However, if you take the time to really see what is going on its not quite as arcane as it might seem at first.

Redux

Stores

A Redux store holds your application’s state.  State can be modified by dispatching an action.    In vanilla Redux you would use the method store.dispatch(action) to do this.

Actions

Actions provide information for the store.  Although Redux is different from an MVC framework, I would say that an action is basically the equivalent of a model in MVC.  It essentially provides the raw data for your application’s state.  An action is actually just a regular Javascript object, but it must structured in a certain way.  An action could look like this:

{
  type: ADD_TODO
  todo: "Do stuff"
}

You can see that this action has two parameters. The first is type, which must always be present. The todo key can really be anything that is descriptive of the data being passed. In this case it is todo. With this data in the action, reducers will do the job of modifying the application’s state.

Reducers

An action only contains data. By itself, it is mostly useless. Somehow, it must be used to update your application’s state. This is where reducers come in to play. A reducer takes an action and based on action type (“ADD_TODO” in example above), it will decide what needs to be done with the data (ie. how will it effect your application’s state). Reducers are where application state gets update. It is important to note that you should never actually mutate your state. Instead you want to create a copy.

A reducer might look something like this:

function todo(state=initialState, action) {
  switch(action.type) {
    case: ADD_TODO
     //never modify state
     return Object.assign({}, state, {
        todos: [
          ...state.todos,
          {
            text: action.text,
            completed: false
          }
        ]
      })
    default:
     return state;  
  }
}

This reducer has effectively added the new todo into a list of todos. Now you can do whatever it is that needs to be done to update your application with the new state.

The diagram below illustrates a typical Redux flow.

Use with React

The best way to use Redux with React is the React-Redux library. This library works very well when used properly. As I mentioned earlier, it can sometimes seem magical if you don’t fully understand what is happening behind the scenes. Understand however, that it is at its core just a library to allow to your React components to access your Redux state.

The first step to using React-Redux is to install the React-Redux library. I will not be covering this. If you are using npm its a pretty simple npm install.

Lets assume that you have already created your reducers and actions. A project folder structure may look something like this:

-actions
--actions.js
-reducers
--index.js
--reducers.js
-components
--app.js
-index.js

Assume an index.js file (in your application root) which houses the bulk of your app. Also assume your reducers are in a module called RootReducer. This module would be located in the file reducers/index.js A possible first step would be to create a store using the Redux method: createStore in index.js.

It might look something like this:

import App from './reducers';
let store = createStore(RootReducer);

You would then need to use the React-Redux component called Provider to give your components access to the store.

<Provider store={store}>
<App />
</Provider>

This Provider just houses the application’s state. All components that will be using Redux stores need to be a child of this component. In the case above App is the only element, but its children will also have access.

Now that there is a store, your React components need to be able to communicate with it and get the state. This is where connect comes into play. This is a special function from the React-Redux library that simply connects a React Component to a Redux store. We refer to these components as containers.

This function takes two arguments: mapStateToProps, and mapDispatchToProps. mapStateToProps is a function that you create that will return an object that is used to map your component’s properties to the application’s state. mapDispatchToProps can also be a function to map an action creator to your component’s props, so that your component can not only create an action, but dispatch it to update your state. If you do not need to use either of these arguments you could pass in null or undefined.

mapStateToProps

An example of using mapStateToProps is below:

function mapStateToProps(state) {
  return {todo: state.todo};
}

Now your container has access to state.todo by calling this.props.todo with in your container.

mapDispatchToProps

This maps your action creators to to your React Component’s props. If you have a button click, for example you can have it create and dispatch your action by adding this action creator to this argument because the action creator now becomes one of your component properties. It can then be called with this.props.actionCreator() (within your React component) and the action will then be automatically dispatched, updating your application’s state through your reducer. An example of this function might look something like this:

function mapDispatchToProps(dispatch) {
  return bindActionCreators({addTodo}, dispatch)
}

Now our component can call this.props.addTodo() and then dispatch the action that is created.

Putting It All Together

Below is an example of a trivial React Redux Application. This example is obviously overkill to use Redux and React, but it gives a good illustration in how it might be used in any application.

See the Pen awQaZg by Daniel Miller (@dmiller5383) on CodePen.

There are two react components: One is a button and the other is a div that changes text when the button is pressed. Each of these components are turned into a container and mapped to the Redux Store’s state through the connect. There is only one property that needs to be managed with Redux State: message. Both components are connected to this. For the button we use mapDispatchToProps to map the action creator changeMessage to it. When clicked, this will update the message in the Redux Store’s state and also on each Container’s property.

Conclusion

React components are a great way to organize your Javascript. React does not provide a way to manage your application’s state. This is where Redux comes into play. If you are working on a large application, state management is very important. Redux can be used with React for this purpose using the React Redux library. There is a learning curve, especially if you aren’t familiar with ES6 and Javascript modules. I believe that this is the future of front end development and anyone who is serious about the craft should invest some time in learning it.