How to make Redux more concise

Michael Lin
2 min readJun 22, 2019

--

If you also think that Redux’s Boilerplate code and immutable data update make your code verbose, then this article may be the answer you’re looking for.

First, I’ll get a quick introduction to usm-redux. It is an open source library based on Redux and Immer, and it makes your Redux code incredibly concise.

You don’t use writing cumbersome Redux boilerplate code, nor do you use to write cumbersome immutable data update operations code.

For example:

class Foo extends Module {
@state todos = { bar: { list: [] } };
@action
done(index, state) {
state.todos.bar.list[index].done = true;
}
}
  • No type action
  • No reducers
  • No other boilerplate code
  • Immutable data update more conveniently

More document details are here.

If you think usm-redux can solve your Redux problems, and your current project wants to try to migrate to usm-redux, then here's a complete migration tutorial.

Migration from Redux Boilerplate Code

Use https://github.com/reduxjs/redux/tree/master/examples/todos as an example.

1. Create a migration module

create src/modules/Service/index.js file:

import Module from 'usm-redux'
import todos from '../../reducers/todos'
import visibilityFilter from '../../reducers/visibilityFilter'
export default class Service extends Module {
get _reducers() {
const reducers = this._getReducers(this.actionTypes, {})
return this._proto.combineReducers({
...reducers,
visibilityFilter,
todos,
})
}
}

2. Replace the store

Replace code in src/index.js file:

const store = createStore(rootReducer)

To

const store = Services.create().store

🎉🎉🎉It’s work🎉🎉🎉

3. Dev new feature with usm module model

For example, we need develop counter feature.

4. Create 'src/modules/Counter/index.js' file

import Module, { state, action } from 'usm-redux'export default class Counter extends Module {
@state count = 0
@action
add(state) {
state.count++
}
}

5. Add new module in 'src/index.js'

import Counter from './modules/Counter'
import Service from './modules/Service'
const service = Service.create({ modules: { counter: new Counter() }})
const store = service.store
render(
<Provider store={store}>
<App service={service} />
</Provider>,
document.getElementById('root')
)

6. Add new featrue counter container in 'src/components/App.js'

import React from 'react'
import Footer from './Footer'
import AddTodo from '../containers/AddTodo'
import VisibleTodoList from '../containers/VisibleTodoList'
import Counter from '../containers/Counter'
const App = ({ service }) => (
<div>
<AddTodo />
<VisibleTodoList />
<Footer />
<Counter service={service} />
</div>
)
export default App

7. Add counter container 'src/containers/Counter.js'

import React from 'react'
import { connect } from 'react-redux'
const Counter = ({ add, count }) =>
<button onClick={add}>
{count}
</button>
const mapStateToProps = (_, props) => ({
count: props.service.modules.counter.count
})
const mapDispatchToProps = (_, props) => ({
add: () => props.service.modules.counter.add()
})
export default connect(
mapStateToProps,
mapDispatchToProps
)(Counter)

🎉🎉🎉It’s done🎉🎉🎉

Note: You can also gradually migrate old redcers while developing it in the new module way.

8. Redux Middleware

For example, We use redux-logger middleware, just create a base module.

import { applyMiddleware, createStore } from 'redux'
import logger from 'redux-logger'
import Module from 'usm-redux'
class BaseModule extends Module {
static _generateStore(_, { reducers }) {
return createStore(
reducers,
applyMiddleware(logger)
)
}
}

usm-redux will make you more enjoyable to use Redux.😄

This demo repo: https://github.com/unadlib/usm-redux-migration-demo

USM repo: https://github.com/unadlib/usm

Finally, if you want to learn more about the USM article:

--

--

Michael Lin
Michael Lin

No responses yet