Managing React state with Redux

Managing React state with Redux

Managing React state with Redux

The example of Facebook dealing with chat problem shows how important it is to properly manage the state of web applications (and I mean UI state). Facebook tried to synchronize a counter between unread messages and currently open chatboxes which caused lots of problems for the users.

What is wrong with React state

Using state built in React components is very tempting, but when application gets more complex and lots of parts have to communicate with each other debugging it becomes really hard task. It’s difficult to see the data flow and how various components communicate.

In React, components can easily communicate with their children by passing them props, and children can talk back by callback functions, but what if we need to notify neighbour or some faraway component?

react data flow diagram

Black arrows shows where communication goes just right and red arrows indicate where problems emerge.

Flux as possible solution

Flux is not a library or framework, it’s an application architecture that completes React by utilizing an unidirectional data flow, but you can use Flux with any other library or framework (even with Angular).

simple flux architecture diagram

Source: https://facebook.github.io/flux/docs/overview.html

In this diagram we can see primary mental Flux model.

Dispatcher

It’s a single central hub managing a whole data flow, which distributes the actions to the stores. Every store provides a callback and when a new action is sent to a dispatcher each store receives it via previously registered callback.

Stores

Stores contain all state and logic of application. After store registers itself in dispatcher, it receives the action as a parameter by this callback. Then based on action type, store interprets what should be done with it and finally updates application state.

Views

Views display our state and listen for change events then retrieve new data from the stores and provide new data to all their child views.

Actions

Action is any plain js object with type property defined. You can pass it to a dispatcher, who will send it to his registered stores. We may create a helper methods which sends action to dispatcher.

Redux, implementation of Flux done right

Well, maybe not quite implementation, Redux is strongly inspired by Flux, but does not have concept of a dispatcher and Flux store is equal to Redux reducer. However, I decided to use this library, mostly because it’s simplified a little bit. Actually, the Redux author made a great post answering the question why to use Redux over Facebook Flux, you can read it here.

Redux three principals are:

  • Single source of truth
  • State is read-only
  • Changes are made with pure functions

First rule says that there is only one place where all application state is stored.

The second rule implies that the state is immutable, which means that instead of mutating an existing object a new object with changed properties is created. Sticking to this allows us to create really predictable application.

Last rule tells us that reducer function has to be pure function, and what does it means? A pure function always returns the same result given same parameters eg:

https://gist.github.com/pjazdzewski1990/262c764ad80580370d775320436601cd

Basic counter application

I’m assuming that you know React with ES2015 syntax and also how webpack works. But if you are not familiar with webpack check out my previous post.

Before we start I strongly recommend to install Redux DevTools for Chrome. It will allow you to track state changes in Chrome DevTools.

I created a little boilerplate repo: https://github.com/mdoff/react-redux-boilerplate and after installing npm dependencies it is ready to use. Let’s try to write classic counter application.

This application will have one field to display counter and two buttons to decrement and increment counter. If you are using my boilerplate, copy code below and paste it in src/index.js file.

https://gist.github.com/pjazdzewski1990/3cb978216b471eee83dbc1e5788fa63c

At first, it may look like a lot of code overhead, but when we have large application adding new components really doesn’t take much code.

Let’s have a look on each part, first our reducer:

https://gist.github.com/pjazdzewski1990/164748488e945c32675af0f4be2332dc

Like I wrote earlier, reducer has to be a pure function, it takes two arguments: state and action and it also always have to return correct state value, even without arguments it should return initial state. We need to remember to keep our state immutable, so we can’t return something like that:

state.counter++;
return state;

Instead I’m using spread operator to keep state immutable.

Reducer uses switch to recognize action type and perform right action. You can read more about reducers here

Creating a store:

https://gist.github.com/pjazdzewski1990/bd70169f0491ab32a454a8d65abb52bf

Function createStore takes our reducer as the first argument, initial state is the second argument and a store enhancer is the third, here I’m using it to connect this store to Chrome Redux DevTools plugin.

https://gist.github.com/pjazdzewski1990/9a51f6b1b1b8739acc8f663233a7c69a

Counter component takes in props 3 arguments, counter value, onIncrement and onDecrement functions except that it’s just a simple view.

https://gist.github.com/pjazdzewski1990/587188f62d6f9364e65ac80eaf311d89

Here we define 2 functions, first one mapStateToProps allows to map our state to fit needs of specific view, we can filter some values or change the order of some kind of items held in state, this function have to return object.

The second function mapDispatchToProps returns object with functions allowing to dispatch actions to store, in that way views doesn’t have to know what actions are dispatched.

Function connect takes object returned by mapStateToProps and mapDispatchToProps then merge them with props object and inject them into Counter props. This function returns a wrapped component and that is why we need to reassign the Counter component.

https://gist.github.com/pjazdzewski1990/ceab292401b68b297d7a90125e84b9ad

If we want to use the connect function, first we need to wrap our root component with Provider it binds passed store to all his children.

Summary

After some time spend on working with Redux I think that this is one step in right direction in JavaScript world. Using React and Redux with immutable state and React allows to avoid costly re-rendering and to keep an eye on application state.

I also wrote more complex example of Redux application available here

Links

Do you like this post? Want to stay updated? Follow us on Twitter or subscribe to our Feed.

See also

More on frontend

Download e-book:

Scalac Case Study Book

Download now

Authors

Tomasz Lewiński
Tomasz Lewiński

I'm JavaScript and frontend developer, after some time as Full-Stack I decided to focus more on the front part of projects because it's what I enjoy the most.

Latest Blogposts

23.04.2024 / By  Bartosz Budnik

Kalix tutorial: Building invoice application

Kalix app building.

Scala is well-known for its great functional scala libraries which enable the building of complex applications designed for streaming data or providing reliable solutions with effect systems. However, there are not that many solutions which we could call frameworks to provide every necessary tool and out-of-the box integrations with databases, message brokers, etc. In 2022, Kalix was […]

17.04.2024 / By  Michał Szajkowski

Mocking Libraries can be your doom

Test Automations

Test automation is great. Nowadays, it’s become a crucial part of basically any software development process. And at the unit test level it is often a necessity to mimic a foreign service or other dependencies you want to isolate from. So in such a case, using a mock library should be an obvious choice that […]

04.04.2024 / By  Aleksander Rainko

Scala 3 Data Transformation Library: ducktape 0.2.0.

Scala 3 Data Transformation Library: Ducktape 2.0

Introduction: Is ducktape still all duct tape under the hood? Or, why are macros so cool that I’m basically rewriting it for the third time? Before I go off talking about the insides of the library, let’s first touch base on what ducktape actually is, its Github page describes it as this: Automatic and customizable […]

software product development

Need a successful project?

Estimate project