I create a package to simplify the work when using useReducer

jason89521

Xuan

Posted on May 1, 2022

I create a package to simplify the work when using useReducer

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

  1. Use an object to generate a reducer
  2. Automatically generate action creators
  3. 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}),
}
Enter fullscreen mode Exit fullscreen mode

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},
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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>
  )
}
Enter fullscreen mode Exit fullscreen mode

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>
  )
}
Enter fullscreen mode Exit fullscreen mode

As you can see, we can write less code with use-case-reducers. Hope this package will help you. Have a good day!

💖 💪 🙅 🚩
jason89521
Xuan

Posted on May 1, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related