Michael Lin
3 min readMar 31, 2019

--

A concise design that completely changed Redux

It’s been almost four years since the first Redux commit. During this time, there are a variety of encapsulation practices for Redux, in which OOP design is particularly prominent, and usm-redux is a completely changed Redux inherent usage of the library.

Basically, usm-redux is a Redux re-encapsulation library that is completely created for OOP, making the use of Redux incredibly concise.

Let’s first look at a classic Todo example in Redux official document:

import { createStore, combineReducers } from 'redux'// action
let nextTodoId = 0
const addTodo = text => {
return {
type: 'ADD_TODO',
id: nextTodoId++,
text
}
}
const setVisibilityFilter = filter => {
return {
type: 'SET_VISIBILITY_FILTER',
filter
}
}
const toggleTodo = id => {
return {
type: 'TOGGLE_TODO',
id
}
}
// reducers
const todos = (state = [], action) => {
switch (action.type) {
case 'ADD_TODO':
return [
...state,
{
id: action.id,
text: action.text,
completed: false
}
]
case 'TOGGLE_TODO':
return state.map(todo =>
(todo.id === action.id)
? {...todo, completed: !todo.completed}
: todo
)
default:
return state
}
}
const visibilityFilter = (state = 'SHOW_ALL', action) => {
switch (action.type) {
case 'SET_VISIBILITY_FILTER':
return action.filter
default:
return state
}
}
const todoApp = combineReducers({
todos,
visibilityFilter
})

It’s just about writing a simple todo, but that’s obviously Redux’s boilerplate.

Here is a usm-redux Todo example (exactly the same logical implementation as above):

import Module, { state, action } from 'usm-redux'class TodoList extends Module {
@state todos = []
@state visibilityFilter = 'SHOW_ALL'
nextTodoId = 0
@action
add(text, state) {
this.nextTodoId++
state.todos.push({
text,
id: this.nextTodoId,
completed: false,
})
}
@action
toggle(id, state) {
const todo = state.todos.find(todo => todo.id === id)
todo.completed = !todo.completed
}
@action
setVisibility(filter, state) {
state.visibilityFilter = filter
}
}

usm-redux has only the definitions of @state and @action, in addition, it's exactly the same as the OOP of the class that you often use.

In a comparison between a fully equivalent TODO examples, we can see that the usm-redux logic code is close to the way it is closer to OOP, making it easy for people who want to use OOP. At the same time usm-redux also provides a decorator @computed cache for computing derived data.

class Shop extends Module {
@state goods = [];
@state status = 'close';
@action
operate(item, status, state) {
state.goods.push(item);
state.status = status;
}
// call -> this.operate({ name: 'fruits', amount: 10 }, 'open');
@computed
shortages = [
() => this.goods,
(goods) => goods.filter(item => item.amount < 5)
];
}

The modular usage of usm-redux will make your project also has more cohesion with business logic. At the same time with React Hooks, let React+Redux easily reach high cohesion and low coupling.

BTW, usm-redux is a concept based on the universal state module designed usm. Simply, usm is a way to make it easy for you to use mainstream state libraries such as Redux, Vuex And MobX without bothering to learn and use them separately.

For more information about usm-redux and usm, here is this repo: https://github.com/unadlib/usm

--

--