A Note on Redux

Introduction

This a note on Redux.

Background

Angular, React, and Vue all encourage component based programming. But all share a natural problem on how to handle the shared data and the communication among the components. To address this problem, Redux was introduced. In this note, I will give a small example using Redux with React.

The Node Project & Webpack

The attached is a Node project to serve the content implemented in the "client" directory. While it heavily referenced the project created by the "create-react-app" script, the project is a lot simpler and a lot smaller, so the Webpack and React program can be easily added to the other environments, such as Visual Studio, Maven or Eclipse. The following is the "package.json" file.

To run the application, you need to first transpile and pack the React program into a bundle. You can use the following command to create a development bundle.

npm run pack-d

If you want to set a watcher to regenerate the bundle whenever you save the related files, you can use the following command:

npm run pack-dw

You can use the following command to create a production bundle, which takes a longer time to generate but has a much smaller bundle size.

npm run pack-p

After generating the bundles, you can start the Node server to serve the application.

node app.js

Redux & Actions & Reducers & Connect & Provider & React

This is an example of Redux in React, where Redux is a framework to share date and communicate among the React components. The Redux has three principles:

Single source of truth - the data is stored in an object tree inside a single store

State is read-only - the only way to mutate the state is to emit an action, an object describing what happened

Mutations are created by pure functions - the functions are called reducers

This note is about Redux but not React. If you are not familiar with React, you can take a look at my earlier notes. To use Redux with React, you will need the "redux" and "react-redux" npm packages. A typical Redux React application will have the following building blocks:

Actions - the helper functions to generate Redux events

Reducers - the functions to handle the events and return the appropriate state entry by the type of events

Components - the React components that are connected with Redux so they can dispatch events and get notified by the state changes

The store and the provider - a store needs to be created by the reducers and associated with a provider so it can communicate with the components

With the Redux concepts in mind, let us take a look at the concrete example implementation with React.

The Actions

The actions are helper functions to generate action objects. A typical action object has a type and a payload property. The "addNumberEvent" creates an action object to instruct the reducer to add a number to the list in the data store. The "clearNumbersEvent" creates an action object to instruct the reducer to clear the list of numbers. The action objects are processed by the reducers.

A reducer function takes two parameters, the state entry and the action object.

It is important that the state entry has a default value, it is the initial value of the state entry in the Redux store object.

The reducer function mutates the state entry based on the information in the action object.

If no action is taken, the reducer function should not alter the state entry but simply return it back to the caller.

In a typical Redux application, we may have multiple reducers. It is important to export the "combineReducers".

The Redux framework uses the information in the reducers combined to create the initial state of the store. The property name of each data entry in the Redux store corresponds to the function name of each reducer.

To use Redux, we need to create a store based on the combined reducers.

The stored needs to be assigned to a "Provider" component and the other components who share the store need to be the children of the "Provider" component.

Now we completed a simple React application with Redux. It may seem a little too complicated for the kind of work that we want to do, but when your application gets larger, you will see the benefit from Redux. If you take a look back at what we have done, you should notice that the components and the Redux reducers can be developed independently but simply connected to each other through the Redux framework to nicely share data and communicate with each other.

Run the Application

If you transpile and bundle your React package and start your node server, you can run the application by "http://localhost:3000/".

You can click the "Add..." button to add a random number to the list and you can clear the numbers by the "Clear..." button. Although none of the React component actually holds the data, they share the data in the store and communicate nicely by the Redux framework.

Points of Interest

This a note on Redux.

While Redux is a nice framework, it certainly has some rooms for improvement for simplicity and performance and scalability.

I hope you like my postings and I hope this note can help you one way or the other.