Dan Abramov, the creator of Redux recently published an article “You Might Not Need Redux” where he pointed out that developers opt Redux as a de facto when building React apps, without even considering if they actually need it.
Redux is not to be blamed. Like any other library, it offers some tradeoffs like touching three files to achieve simple tasks, describing the state and actions as plain objects and arrays and handling the logic via pure functions. These constraints enable easier debugging, better testability, guarantee the user-interface to be predictable with the state and a lot more out-of-the-box.
But, writing so much to do so less brings in some annoyance and slows down the overall development.
Do we really need a state management library?
Can’t we just define plain ES6 classes as models and store their instances in an array collection without using a library? Yes, we can! But, the problem isn’t the data storage or retrieval.
The real problem is how do we detect data mutation and handle its side-effects. Side-effects of data mutation includes actions like
- Syncing the UI with the change in data
- Re-calculating the computed variables
- Navigating to a different route
If we mutate the data using assignment operator (like user.name = “John Doe”), we don’t have a mechanism to detect the change (Object.observe() has been deprecated).
That’s exactly where we need state management libraries.
Redux detects such changes by enforcing data mutation via pure functions called reducers.
How other frameworks solve it?
- Dirty checking: Angular 1.x uses “dirty checking mechanism” where the new and old data tree are deeply compared in successive cycles. It is tempting at first but kills the performance at scale.
- Reactive programming: Angular 2 and Meteor use the concepts of reactive programming which makes data propagation and change detection easy to understand and scale.
- Observer pattern: Similar to reactive programming concepts, Observer pattern triggers events on data mutation. Knockout.js and MobX use observer pattern.
- Setter and Getter: The good old setter and getter methods have solved the problem of change detection for years which has been used by Ember and Backbone.
What are the alternatives to Redux?
this.setState()
React comes with it’s own method of change detection at the component level. If you’re new to React, just stick to this.setState() approach. It works well for small apps. For eg: Simple Todo App
Reactive and Observer patterns with React
- MobX (aka mobservable): It has a very small footprint. If you’re comfortable using object-oriented pattern, this one is for you. With the use of ES6/7 decorators you hardly feel you’re using any library.
- RxJS: “The Reactive Extension of JavaScript” as they call it. RxJS is a beast in itself. In simple terms, RxJS = Observables + Operators + Schedulers. Though it’s famous as a standalone library, it has some neat bindings for React.
Other Flux implementations
My Personal Choice: MobX
[Update Oct 24th 2017] I have started to use mobx-state-tree which is a state container and uses MobX.
Why MobX?
- The best part of MobX is that it takes the pain away of adding listeners for the data changes, it transparently applies reactive programming concepts (TFRP) to your data models and updates a part of the UI whenever it is required.
- Object Oriented concepts for the win: You can use the good old object oriented concepts and apply it to the data models in your app.
- Easy to document and communicate: As a tech lead, MobX makes my job very easy to document all the classes and stores with the properties and methods which needs to be built.
- Rapid development: You can focus on the business logic of the app and deliver things quite quicker compared to other libraries.
- Added lifecycle hook whenever there is a reaction: mobx-react adds a lifecycle hook called componentWillReact() for reactive updates. This hook can be used in Routers and Navigators.
Tradeoffs?
If you choose one library over the other, you gain something and you lose something. Here are some of the tradeoffs MobX offers:
- Since we use classes and derived objects instead of plain JavaScript objects, the data can’t be serialized straightaway. You need to write your own toJS() and fromJS() methods with every class
- Data needs to be serialized every time when the data goes out of the execution environment like when making API calls, storing it in LocalStorage, populating the stores in the back-end from other data sources and so on.
- Unlike Redux, features like undo / redo and time travel of data changes needs to be built by hand.
The bottom line
It’s not set in stone that you have to use a specific state management library with React. It’s a personal choice of paradigm which you and your team is comfortable with. The community can be misguiding sometimes. So, before you include a library, think twice about the constraints and tradeoffs the library offers.
Did I miss anything? Feel free to add a response to the article for any correction, opinions and discussions.
If you liked the article, consider recommending it. I am Sanket and we are building NativeBase.io at GeekyAnts.
Hacker Noon is how hackers start their afternoons. We’re a part of the @AMIfamily. We are now accepting submissions and happy to discuss advertising &sponsorship opportunities.
To learn more, read our about page, like/message us on Facebook, or simply, tweet/DM @HackerNoon.
If you enjoyed this story, we recommend reading our latest tech stories and trending tech stories. Until next time, don’t take the realities of the world for granted!