Untangling reducers into a configuration

The one thing that has irked me in every reducer based state management system is the reducer itself. It is a daunting task to be a full time state ninja slicing/merging arrays and objects, flipping/toggling countless flags and extracting/assigning values in every decrepit corner of your application state. To add insult to injury, all the above tasks have to be done keeping in mind the idiosyncrasies of our overlord, the state reducer, whose purity must be preserved in all its glory at all times. Kubric's reducer-factory tries to put an end to the tyrannical rule of reducers by reducing them to a mere configuration and freeing the developer from the shackles of dull state operations.

Notwithstanding the tall claims made in the above tirade, Redux with its reducer based state management is one of the best options available to a web developer when they find themselves responding to questions like - "Does your webapp have a predictable state?" - with answers like - "Given ample time and resources, I can predict it with a fair amount of certainty". It came in at a time when developers using Flux libraries started getting frustrated with the boilerplate code involved in getting it going. Redux was heralded as a champion when it took center stage retaining the best things from flux architecture and doing away with majority of the boilerplate. But lately it has been drawing flak for the exact same crimes that it's predecessors were charged with - "too much boilerplate", "complex to configure" etc. The image below highlights those facets of Redux that have gained notoriety amongst the renegade faction along with the crimes that they have been accused with. A multitude of tools have been devised(redux-toolkit, rematch) with the express intention of putting an end to these issues.

Redux pain points
Redux's rap sheet

Being a developer who has worked on pre-Redux state management, I've rarely been frustrated with the the above aspects of Redux that people generally complain about. I was more frustrated about the sheer volume of repetitive code that I had to write on a daily basis to do mundane state operations

  • Extracting a value from the action object and assigning it to some part of the state
  • Appending, deleting, editing a value in an array
  • Switching on/off boolean flags

As the application grows bigger, so does the state and along comes the problem of writing, testing and maintaining the complex state logic embued in a plethora of reducers. Reducer factory is an attempt at mitigating some(eventually most) of these troubles by delegating some day to day state operations(like the ones listed above) to a configuration and write reducer code only where complex logic is warranted.

Use case

Consider a user profile page that has the following fields

  • name - Name of the user
  • enabled - A boolean field that determines whether the profile is enabled or not
  • email - Email of the user
  • gender - Gender of the user
  • options - An array of options selected by the user
  • dialogOpen - Denotes whether the dialog to save the user details is open or not

The actions to the store are in the following format

The task is to write a reducer that honors the following actions

  • PROFILE_FETCHED: Fills all fields from the payload with transformation applied to the fields enabled, options and gender
  • ENABLED: Turns on the enabled flag
  • DISABLED: Turns off the enabled flag
  • NAME_CHANGED: Sets name field
  • EMAIL_CHANGED: Sets email field
  • GENDER_CHANGED: Sets gender field with lower case transformation
  • OPTION_SELECTED: Appends an option to the options array
  • TOGGLE_CONFIRMATION: Toggles the dialogOpen flag
  • CLEAR_FORM: Clears all the fields to defaults

Coded reducer

The reducer to achieve the above looks like this

Configured reducer

The entirety of the above reducer can be reduced to a JSON configuration using reducer-factory

If an action warrants the use of explicit coding, the above config can be extended with a reducer through which the action will be passed after it has been run through the config. If there is a piece of custom app specific state logic that is being used across multiple reducers, reducer- factory also allows for defining this logic as a custom state operation which can then be used in reducer configurations throughout the app.

The library still has a long way to cover before it can confidently claim to have ridden all mundanity in the life of a web developer with regards to reducer coding. But I believe the ability to configure the aforementioned 3 operations goes a good way in removing the bulk of state operations in most applications. At least, it did so in all of our webapps.

Share this article: Link copied to clipboard!