Syntactic sugar in Redux: “Type to reducer” and “Redux toolkit”

Maxilect
7 min readDec 16, 2022

--

Today we will talk about two convenient ways to reduce the routine in Redux, which we use in different parts of our project. We will discuss a little-known “Type to reducer” library and the “Redux toolkit.” Without them, it was difficult for us to use Redux.

The article was written following the results of an internal meetup for non-frontend developers, which took place a couple of months ago.

All interfaces in Maxilect products are built on React. In Reacts logic, the interface is assembled from components, each of which has its state. In a bare React application, this state can only be passed down a hierarchical chain of components from top to bottom — a kind of unidirectional data flow.

A hierarchical chain is a handy concept for small projects. However, when the application grows and the state becomes large (this includes current authorized users, etc.), the frontend has to store a lot of data. There is a problem with the transfer of this data between components. Starting from a particular scale, using only unidirectional flow is inconvenient. Working with such code becomes painful.

Data flow between components.

Here the Redux comes to the rescue. Redux is the state store for JavaScript applications. Redux eliminates the need for duplicating state information in the components themselves. In general, it helps to put things in order and simplifies the work with the code (at the same time, it improves the application’s performance).

Redux components can call dispatch to change state. An action is passed to dispatch, which tells what exactly needs to be done with this state. Next, the reducer fires. Reducer contains the business logic of state change. After that, the new state update all relevant application components. As a result, users see up-to-date information in the interface.

How Redux Works (https://dev.to/danielkrupnyy/redux-basics-cheat-sheet-1kdn)

As the application grows further, new complexity comes in.

In a large application, setting up Redux from scratch is like launching a spaceship, especially if you’ve never used one before. To set up the repository, you must copy a huge copy-pasted code. Also, to get Redux to do something useful, you will likely need to use additional libraries. If you want to see the current state in the browser while debugging — look for a library. You need a synchronous transfer — too. As a result, the project grows like a snowball.

At this point, you turn to auxiliary tools that make it easier to work with Redux, which I want to talk about today.

Type to reducer

When I came to the project, “Type to reducer” was already there.

“Type to reducer” is a small library that contains a function of the same name that makes it easy to create a reducer. This is a rather unpopular thing, which. It has only 125 fans on GitHub (https://github.com/tomatau/type-to-reducer). I suspect that when the project started, there were no more popular tools for solving the same problem. Now, this choice may seem strange, but it was fully justified at that time.

The Type to reducer function takes a reducer map object as input. Input is a collection of key-value pairs, where the Action name is the key, and the reducer function is the value, which returns the modified Store.

As an example, I will give a code snippet from our project.

Here is a code fragment from our project.

A reducer called “accountManaging” changes the isLoading parameter to true when the action FETCH_LIST_START is triggered (in the interface, the user sees the preloader and understands that the file is being loaded). It can process successful loading (FETCH_LIST_SUCCESS) — which again translates isLoading to false and returns a list — it forwards the data received from the server. It also handles errors (FETCH_LIST_ERROR).

The second argument is the initial state of the component (accountManagingInitState).

In classic Redux, action and reducer are separated from each other, and this complicates development. “Type to reducer” combines them into a common package, where the new state of the application is already described. In fact, this is just a tiny utility for organizing reducers. In our project, “Type to reducer” completely solves the problem.

Redux toolkit

Some time ago, we needed to cut the entire business out of the project, leaving clean pattern code to reuse in another module. At this stage, we decided to abandon the unpopular “Type to reducer,” replacing it with something more interesting — the “Redux toolkit.” If “Type to reducer” is just a tiny utility, then “Redux toolkit” is a complete toolkit. It solves the same problem but does it more elegantly.

“Redux toolkit” is a complete package for Redux development. Unlike the first tool, it has 8.4K fans on GitHub (https://github.com/reduxjs/redux-toolkit). By the way, there is no need to install Redux separately to work with the “Redux toolkit” — it has everything out of the box, including the classic developer tools for debugging code.

To demonstrate the capabilities of the “Redux toolkit,” I wrote a simple application — I will show its implementation in pure Redux and with the “Redux toolkit.”

Let’s imagine we have a simple counter with an initial value of 0. It has two buttons — a plus and a minus.

Here’s what classic Redux implementation looks like:

classic Redux implementation

The left side is self-explanatory — we just created a Store.

On the right side, we first declared text constants, then action types (the same that we passed in “Type to reducer” as a key that changes the function’s properties). After that, the initial state is set — 0.

Further, the reducer accepts an action and, depending on its type, returns a new state — increased or decreased by one relative to the current one (the action creators are placed in the code below).

Everything seems clear. The problem is that when the project grows, there are a lot of action creators. Processing each of them, you have to perform many routine actions. It’s easier to do it through the tool — Redux toolkit.

Redux toolkit implementation

There is much less code in this case. On the left, like last time, is the creation of the Store. Unlike the previous time, we do not include developer tools since the “Redux toolkit” has everything you need. On the right, again, are the initial values ​​and actions that are set using the createAction function. Then, we define the reducer.

The code is similar to what we wrote using “Type to reducer.” However, in my opinion, there is one interesting difference. In accordance with the concept of classic Redux, we cannot mutate the state. Each time we do not change the object but return a new one — with a different state. In the Redux toolkit, state mutation is available to us (although all this is syntactic sugar, which turns into regular Redux under the hood of the library engine). From a syntax point of view, this is more convenient and clearer.

There is also one more exciting feature I want to discuss. We use slices in our project (this is also part of the Redux Toolkit library). If the Store is the entire state of our application, then the slice is its part. We can make a separate slice for users, notifications, notes, etc. It’s convenient enough. We are not getting new functionality, but we can further reduce the code.

To create slices, use the createSlice function, which is available in the “Redux toolkit.” As input, it takes the name of the slice and the initial state. Next, we describe reducers in the same way as we did above. This function returns a slice object that contains the generated reducer and action functions inside the object. This makes the code even more compact.

In general, both tools help us reduce the routine of projects. But the Redux toolkit is more recent and functional. If you’re starting a large Redux project from scratch, I suggest you at least consider using it.

The article is based on materials from Dmitry Titov.

PS. Subscribe to our social networks: Twitter, Telegram, FB to learn about our publications and Maxilect news.

--

--

Maxilect
Maxilect

Written by Maxilect

We are building IT-solutions for the Adtech and Fintech industries. Our clients are SMBs across the Globe (including USA, EU, Australia).

No responses yet