I create a package to simplify the work when using useReducer
Xuan
Posted on May 1, 2022
Using useReducer
to handle complicated state is preferable than using useState
. However, writing a reducer is kind of annoying because we may need to write so many switch/case
to determine which action we are going to handle. Furthermore, we may prefer writing action creators to generate actions instead of writing an action directly.
To solve these problems, I write a package called use-case-reducers to simplify our work.
Features of this package
- Use an object to generate a reducer
- Automatically generate action creators
- Allow mutating state in case reducer
Use an object to generate a reducer
Instead of writing a reducer function, use-case-reducers use an object containing case reducers to generate a reducer. A case reducer is a function that only handles one case of actions. For example, if we want to handle a counter state with two actions increment
and add
, then the object may look like:
const caseReducers = {
increment: state => ({count: state + 1}),
add: (state, amount) => ({count: state + amount}),
}
Automatically generate action creators
use-case-reducers will generate all action creators corresponding to the case reducers you pass in. Take the above caseReducers
for example, it will generate two action creators increment()
and add(amount)
.
Allow mutating state in case reducer
This package use immer in the generated reducer, so we can mutate the state inside our case reducers. We can rewrite the above caseReducers
to:
const caseReducers = {
increment: state => {state.count += 1},
add: (state, amount) => {state.count += amount},
}
This feature may be useful when our state is very complicated.
How to use this package
Use npm
or yarn
to install it as a dependency:
npm install use-case-reducers
#or
yarn add use-case-reducers
We are going to write a component with a counter state and use this package to update it.
import useCaseReducers from 'use-case-reducers'
const initialState = {count: 0};
const caseReducers = {
increment: (state) => {state.count += 1},
add: (state, amount) => {state.count += amount},
};
const Counter = () => {
const [state, dispatch, {increment, add}] = useCaseReducers(caseReducers, initialState);
return (
<div>
count: {state.count}
<button onClick={() => dispatch(increment())}>increment</button>
<button onClick={() => dispatch(add(10))}>add 10</button>
</div>
)
}
Let's look the same component but writing with useReducer
.
import {useReducer} from 'react'
const initialState = {count: 0};
const reducer = (state, action) => {
switch(action.type) {
'increment': {
return {count: state.count + 1};
}
'add': {
return {count: state.count + action.payload};
}
}
}
const increment = () => ({type: 'increment'});
const add = (amount) => ({type: 'add', payload: amount});
const Counter = () => {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
count: {state.count}
<button onClick={() => dispatch(increment())}>increment</button>
<button onClick={() => dispatch(add(10))}>add 10</button>
</div>
)
}
As you can see, we can write less code with use-case-reducers
. Hope this package will help you. Have a good day!
Posted on May 1, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.