Applying OOP to a universal front-end state module with Redux/MobX/Vuex
2019-03-25

This is a proposal for a universal state management module design rooted in the OOP paradigm.
Motivation
As front-end single-page applications become more complex, teams often adopt state management libraries or state containers to manage business state. At the same time, they need a module design that is easier to compose, test, and reuse.
The front-end ecosystem has many state management options, including Redux, MobX, Vuex, and the state management patterns built into Angular. Redux is a predictable state container based on immutable data. MobX provides observable state management. Vuex offers centralized observable state management for Vue.js. Angular already has its own modularization model, but other state management libraries have only started addressing modularization requirements for complex systems in recent years.
In this article, let’s explore an OOP modular design that has universal support for popular state management libraries.
Universal state module
Object-oriented programming (OOP) is commonly used in the architecture design of large front-end projects. The following questions often appear when choosing a state management library:
- Is Redux or MobX more suitable for React?
- Is Redux suitable for OOP?
- What are the pros and cons of using MobX’s observable in React?
- How to do OOP with Vuex?
Front-end architectures are often tightly coupled to their state management libraries. Once a state management library is selected, switching to another usually requires major refactoring. Any system built on such an architecture is therefore locked into the same state library.
Better front-end architecture should be flexible and scalable. This is especially important for integration-oriented libraries, where adapting to target environments and SDK architectures is critical. To create modules that work with React+Redux, React+MobX, Vue+Vuex, and Angular, we need a universal state module design.
Design Goals
- Object Oriented
- Simple & Flexible
- Dependency injection
Proposal
Based on this idea, we propose a new Universal State Module library: usm.
Let’s start with a typical Redux example of a counter:
1 | import { createStore } from 'redux'; |
USM supports Redux, MobX, Vuex and Angular. It provides usm, usm-redux, usm-mobx and usm-vuex packages. Here is the same counter using usm-redux:
1 | import { state, action, createStore } from 'usm'; |
The same counter implementation above is based on the object-oriented paradigm. ES6 class syntax is intuitive and concise. If this design can work across state management libraries, it can provide a more flexible development experience with better readability and maintainability.
USM has four sub-packages: usm, usm-redux, usm-mobx, and usm-vuex. usm-redux is used in this example. It is based on Immer, which allows immutable Redux state to be updated with mutable syntax.
The following code demonstrates how the usm-redux module can be used with the connector from react-redux:
1 | // index.js |
1 | // app.js |
And here is the same counter working with mobx-react using usm-mobx:
1 | // index.js |
1 | // app.js |
Using usm-redux with react-redux and usm-mobx with mobx-react demonstrates that the core implementation of the state module can remain the same even when the connectors are different. This is the core principle of the Universal State Module proposed here.
Decorators
usm provides the @state decorator to mark state and the @action decorator to mark methods that update state.
1 | class Shop { |
Conclusion
usm is a module design that bridges differences among Redux, MobX, and Vuex when used with view layers such as React, Vue, and Angular. It is designed to help you build libraries that can work across different front-end architectures.
Modules built with usm can avoid much of the boilerplate introduced by state libraries such as Redux. More importantly, the object-oriented nature of usm keeps modules simple and intuitive. usm also makes modules compatible with multiple state libraries and view layers, allowing business logic to be shared across projects regardless of the framework in use.
USM’s repo: https://github.com/unadlib/usm