The TL;DR is Redux tries to place a set of constraints on how and when you're allowed to share state between components and how and when you're allowed mutate that shared state, much like how React and it's virtual DOM abstraction places constraints on how and when you're allowed to manipulate the DOM.
These constraints allows the library to make certain assumptions about state and state changes that enables it to perform global performance optimizations across the entire codebase (namely performing only shallow equality checks on all state-mapped props when determining whether or not to rerender, because it can assume all state changes will result in a reference change) that would otherwise have to be performed for each component on a case by case basis, and micro-optimized by each individual developer by hand.
These constraints also allows tooling authors to make these same assumptions, which is what enables the best-in-class tooling that Redux developers have access to, like time traveling debugging and state change replays. These tools would simply not be possible to build in a generalizable way if your codebase didn't allow them to make the same assumptions (and adhere to the corresponding constraints when it comes to state sharing and state mutations) as it could for a Redux codebase.
The post has a whole list of very compelling use cases/tooling that are either made possible by or at least made completely trivial by the enforcement of these constraints around state mutations:
> These limitations are appealing to me because they help build apps that:
> Persist state to a local storage and then boot up from it, out of the box.
> Pre-fill state on the server, send it to the client in HTML, and boot up from it, out of the box.
> Serialize user actions and attach them, together with a state snapshot, to automated bug reports, so that the product developers can replay them to reproduce the errors.
> Pass action objects over the network to implement collaborative environments without dramatic changes to how the code is written.
> Maintain an undo history or implement optimistic mutations without dramatic changes to how the code is written.
> Travel between the state history in development, and re-evaluate the current state from the action history when the code changes, a la TDD.
> Provide full inspection and control capabilities to the development tooling so that product developers can build custom tools for their apps.
> Provide alternative UIs while reusing most of the business logic.
You could certainly make the case that Redux is not necessary for building a React app. Or the case that the additional boilerplate and constraints it places upon you could be a net negative for apps that are not sufficiently complex to warrant them. In fact, that's exactly the case that the linked post tries to make.
And yes, the only reason people use Redux is to introduce rigor (constraints) into their codebase and development workflow. But to insinuate that the rigor and constraints introduced by Redux will only ever be a net negative in terms of developer productivity is to display a fundamental ignorance regarding the vital role that rigor and constraints have always played in software architecture, and the fact that the recent advances in frontend architecture that have been proven to reduce complexity and make large codebases easier to reason about (things like the virtual DOM, unidirectional data flow, immutable state trees/caches, functional/reactive programming, and even the MVC pattern itself) have almost always come as a result of placing more constraints on what the developer is allowed to do.
The TL;DR is Redux tries to place a set of constraints on how and when you're allowed to share state between components and how and when you're allowed mutate that shared state, much like how React and it's virtual DOM abstraction places constraints on how and when you're allowed to manipulate the DOM.
These constraints allows the library to make certain assumptions about state and state changes that enables it to perform global performance optimizations across the entire codebase (namely performing only shallow equality checks on all state-mapped props when determining whether or not to rerender, because it can assume all state changes will result in a reference change) that would otherwise have to be performed for each component on a case by case basis, and micro-optimized by each individual developer by hand.
These constraints also allows tooling authors to make these same assumptions, which is what enables the best-in-class tooling that Redux developers have access to, like time traveling debugging and state change replays. These tools would simply not be possible to build in a generalizable way if your codebase didn't allow them to make the same assumptions (and adhere to the corresponding constraints when it comes to state sharing and state mutations) as it could for a Redux codebase.
The post has a whole list of very compelling use cases/tooling that are either made possible by or at least made completely trivial by the enforcement of these constraints around state mutations:
> These limitations are appealing to me because they help build apps that:
> Persist state to a local storage and then boot up from it, out of the box.
> Pre-fill state on the server, send it to the client in HTML, and boot up from it, out of the box.
> Serialize user actions and attach them, together with a state snapshot, to automated bug reports, so that the product developers can replay them to reproduce the errors.
> Pass action objects over the network to implement collaborative environments without dramatic changes to how the code is written.
> Maintain an undo history or implement optimistic mutations without dramatic changes to how the code is written.
> Travel between the state history in development, and re-evaluate the current state from the action history when the code changes, a la TDD.
> Provide full inspection and control capabilities to the development tooling so that product developers can build custom tools for their apps.
> Provide alternative UIs while reusing most of the business logic.
You could certainly make the case that Redux is not necessary for building a React app. Or the case that the additional boilerplate and constraints it places upon you could be a net negative for apps that are not sufficiently complex to warrant them. In fact, that's exactly the case that the linked post tries to make.
And yes, the only reason people use Redux is to introduce rigor (constraints) into their codebase and development workflow. But to insinuate that the rigor and constraints introduced by Redux will only ever be a net negative in terms of developer productivity is to display a fundamental ignorance regarding the vital role that rigor and constraints have always played in software architecture, and the fact that the recent advances in frontend architecture that have been proven to reduce complexity and make large codebases easier to reason about (things like the virtual DOM, unidirectional data flow, immutable state trees/caches, functional/reactive programming, and even the MVC pattern itself) have almost always come as a result of placing more constraints on what the developer is allowed to do.