Improving Redux

Hello, Habr! I present to you the translation of the article " Redesigning Redux " by Shawn McKay.

Should state management cause problems today? Intuitively, developers see a hidden truth: state management is much more complicated than it should be. In this article, we will analyze a few questions that you probably asked yourself:

  • Do you really need a state management library?
  • Has Redux earned its popularity? Why or why not?
  • Can we come up with a better solution? If so, which one?

Is a library necessary for managing state?

Front-end developer is not the one who simply moves pixels from side to side; true art in knowing where to keep a fortune. It seems complicated only at first glance.

Let's look at the possibilities that React provides us with:


1. Component State

The state is stored inside the component. In React, we update statethrough setState().

2. Relative State

The state passed from parent to child. In React, we pass propsas a property of the descendant component.

3. Provided State

State is stored in the provider ( by provider ), and is available to any component ( the consumer ), located below the tree. Context APIin React.

View stores most of the state. But what about the rest of the code that reflects the core data and logic?

Placing all the code inside the components can lead to a low division of responsibility : the dependence on view libraries is growing, testing of such code is complicated, but the worst thing is that you have to regularly change the way the state is stored.

The structure of the application changes over time, and each time it is more difficult to determine which component needs this or that state. The easiest way to make all the state of the root component, which can be done in the following way.

4. External State

The state can be separate from the components that synchronously “contact” it using the provider / consumer pattern. Most likely the most popular among state management libraries is Redux. Over the past two years, she has gained great fame among developers. So what is the reason for such a love for one library?

Redux more productive? Not. In fact, the application slows down a bit with each new action that needs to be processed.

Is Redux Easy to Use? Of course not.

Native javascript would be simple:


So why can't everyone use it global.state = {}?

Why Redux

Under the hood, Redux is similar to the global TJ object, only wrapped in a series of utilities.

In Redux, you can directly change the status by transmitting ( the dispatch ) actions ( the action ) through these instruments.

The library includes two types of action handlers: middleware & subscriptions . Middleware are functions that intercept actions. Includes tools like logger, devtools, or syncWithServer. Subscriptions are functions used to send changes to components.

Finally, redyusery ( reducer ) - functions that change the state and divide it into small, modular and manageable pieces.

Most likely, Redux is more suitable for storing state than a global object.

Think of Redux as a global object with enhanced capabilities and a simplified way to “transform” state.

Is Redux so complicated?

Yes. There are some undeniable signs that you need to improve the API; we can conclude using the following equation:

We believe that time_saved means the time taken to develop our own solution, and time_invested is equal to the hours spent reading the documentation, taking training courses and learning new concepts.

Redux, in principle, is a simple and small library with a steep learning curve. For every developer who has mastered and benefited from Redux, immersed in functional programming, there is another potential developer who gets confused and thinks “it's not all for me, I'm going back to jQuery”.

You do not need to understand what “comonad” is using jQuery, and you do not have to understand the functional composition to handle state management.

The goal of any library is to make complexity simple with the help of abstraction.

I do not intend to make fun of Dan Abramov. Redux became popular too early in its development.

  • How to make changes to the library used by millions of developers?
  • How do you justify the critical changes that will affect projects around the world?

You can not. But by providing extensive documentation, instructional videos, and community help, you will be invaluable. Dan Abramov did it.

Or maybe there is another way?

Improving Redux

Redux deserves a change, and I armed myself with six of its weak points to prove it.

1. Setup

I suggest looking at the initial configuration of the Redux application (left screen).

Many developers, right after the first step, stopped at a loss. What is thunk ? compose ? Is the function capable of this?

It is believed that Redux is based on a configuration over a composition. The setting should look like the example on the right.

2. Simplify reducers

Redux reducers can use switch constructs that are far from the ones we used to use.

Given that reducers find a match by type of action, we can make each reducer a pure (pure) function that takes state and action. You can shorten the action and only transfer status and data.

3. Async / Await without Thunk

Thunk is widely used to create asynchronous actions in Redux. In many ways, thunk is more like a smart hack than an officially recommended solution. How it works:

  1. You pass the action as a function, not an object.
  2. Thunk checks every action that it is a function.
  3. If everything converges, thunk calls this function and passes some of the store methods to it: dispatch and getState.

Seriously? Should simple actions be typified like an object, function, or even Promise?

Is it possible to use async / await, as in the example on the right?

4. Two types of actions

Think about it, there really are two types of actions:

  1. Reducer action : starts the reducer and changes state.
  2. Effect action : triggers an asynchronous action. May call a reducer action, but the asynchronous function is not able to directly change the state.

The ability to distinguish between types of actions will bring more benefits than the use of "sleds."

5. No more variables storing action type

Why is it customary to separate action creators and reducers? Can one exist without the other? How to change one without changing the other?

Action generators and reducers are two sides of the same coin.

const ACTION_ONE = 'ACTIONE_ONE' - This is an extra side effect of the separation of action generators and reducers. Handle them as a single whole and there will be no need for large files with export types.

6. Reducers are action generators

Combine the elements of Redux according to their purpose, and you will get a simple template.

As a result, following this scenario, the reducer can become an action generator .

Use a naming convention, and the following points will be pretty predictable:

  1. If the reducer is called increment, then the type will be increment. Even better, denote it as “count / increment”.
  2. Each action transmits data via "payload".

Now with the help count.incrementwe can create an action generator directly from the reducer.

Good News: We Can Improve Redux

These problematic parts motivated the creation of Rematch .

Rematch serves as a wrapper around Redux, providing developers with a simplified API.

Here is a complete code example with Rematch:

I have used Rematch in production the past few months. And what I think:

I have never spent so little time managing state.

Redux will not disappear and is not required. Learn this library with less learning curve, less boilerplate and less mental effort.

Try Rematch and find out if you like it or not.
Set a star to let others know about us.

Also popular now: