Photo by Muhammad Haikal Sjukri on Unsplash

"Magic" reducer: yet another approach on state management in React

Or an interesting simplification of something painful

André Ravazzi
2 min readDec 31, 2021

--

Studying state management for React (and Javascript) apps leads to two major approaches: Redux (with its similarly libraries such as X-State, Recoil and MobX) and a "homemade" solution using the React hook useReducer and Context API. In the latter, the Context acts as the dependency injection mechanism that spreads the state within the app boundary, while the reducers hold the transition logics through out the actions, represented by their transitions typing. For example, retrieving a user from an API would lead to 3 types: USERS_REQUESTING in which the request would begin giving a loading time to the interface; USERS_REQUESTED, after a successful response from the endpoint or USERS_FAILED, for failed request. All of those typings represent an action inside the reducer logic that need to be explicitly coded.

In any approach, the most applied pattern is the flux pattern, in which the state changes are controlled by a (proto) state machine and its well-defined transitions. The state itself is allocated in an object serving as the unique and single source of truth. Only the transitions can make changes to the state, never the state object is changed directly by the app logic.

Using the cited methods has its fallbacks: the developer needs to declare explicitly all the transitions types and actions to be dispatched, even if that transition would just read from the state tree, to each domain of the application, as exampled above. It of course might create a lot of boilerplate (and sometime bloated) code.

Now, let's look at the same logic, but using a simpler approach, the "magic" reducer:

The main difference is the reducer. It uses a clever, generic reducer function which, in the end, emulates the useState hook. If you take a close look at setUserState, it has the same behaviour as useState, making this mechanism very familiar in terms of React. It removes the need of registering all the actions typing, thus removing boilerplate, bloated code.

Of course, there is no free meal. If you are not careful, the transition logic might be spread through out the codebase. It ends up depending much on the engineer and architectural organisation.

In the next post I will provide a full example using this "magic" reducer, and discussing whether it can replace entirely the previous state management methods.

--

--

André Ravazzi

Product Engineer @ Builderbinder | Aerospace Engineer | Photography enthusiast | https://unsplash.com/@amravazzi