• Using Immer with React: A simple solution for Immutable States
  • Madushika Perera
  • The Nuggets translation Project
  • Permanent link to this article: github.com/xitu/gold-m…
  • Translator: zenblo
  • Proofread: PassionPenguin, Felixliao

React uses Immer to manage immutable state

In React, immutable states are used to quickly and efficiently compare state trees before and after changes. Thus, each component can decide whether to rerender before performing any costly DOM operations.

I hope you already know:

JavaScript is mutable, and we have to implement immutability ourselves.

Popular state management libraries such as Redux follow the same philosophy. When we use reducers, it expects us not to change the state to avoid any side effects. However, for large, error-prone projects, implementing immutability manually may not be the best option.

Fortunately, there are specialized JavaScript libraries such as Immer. They are designed to achieve the immutability of the state tree.

Introduction and use of Immer

Immer is a small library that helps developers achieve immutable state based on copy-on-write, a technique for copying on modifiable resources.

In Immer, there are three main states:

  1. Current State: indicates the actual status data.
  2. Draft State: All changes will be applied to this State.
  3. Next State: This State is based on changes to the Draft State.

From a performance point of view, compared with using JavaScriptobject.assign()Or Shallow Copy of the expanded operator, Immer performs fairly well. If you are interested in learning more about performance comparisons, please refer to this article:Immer vs shallow copy vs immutability tests.

Immer also reduces the amount of code you need to write to achieve the benchmark results described above, which is one of the reasons why Immer stands out.

Now that you have a basic understanding of Immer, let’s take a look at why Immer is recognized as one of the best solutions for immutability.

How Immer works

If you’re dealing with simple states, you might feel that Immer is making your code more complex. However, Immer becomes very useful when it comes to processing complex data.

To understand this better, let’s look at the famous React Reducer example:

export default (state = {}, action) => {
    switch (action.type) {
        case GET_ITEMS:
            return{... state, ... action.items.reduce((obj, item) = > {
                    obj[item.id] = item
                    return obj
                }, {})
            }
        default:
            return state
    }
}
Copy the code

The code above is a typical simplified example of react-Redux, which uses the ES6 expansion operator to update values down to the nesting level of the state tree object. We can easily reduce the complexity of the above code using Immer.

Let’s look at how Immer can be used to reduce the complexity of the code described above.

import produce from "immer"

export default produce((draft, action) = > {
    switch (action.type) {
        case GET_ITEMS:
            action.items.forEach(item= > {
                draft[item.id] = item
            })
    }
}, {})
Copy the code

In this example, Immer simplifies the code used to extend the state. You can also see it changing objects by using forEach loops instead of ES6’s Reduce function.

Let’s look at another example, using Immer with React.

import produce from "immer";

this.state={
    id: 14.email: "[email protected]".profile: {
      name: "Stewie Griffin".bio: "You know, the... the novel you've been working on".age:1
    }
}

changeBioAge = () = > {
    this.setState(prevState= > ({
        profile: {
            ...prevState.profile,
            age: prevState.profile.age + 1}}}))Copy the code

You can refactor this code by changing the state as shown below.

changeBioAge = () = > {
    this.setState(
        produce(draft= > {
            draft.profile.age += 1}}))Copy the code

As you can see, Immer dramatically reduces the number of lines of code and reduces code complexity.

Use with Hooks

Another important feature of Immer is its support for React Hooks. Immer uses an additional library called use-immer to do this. Let’s look at an example to better understand this.

const [state, setState] = useState({
    id: 14.email: "[email protected]".profile: {
      name: "Stewie Griffin".bio: "You know, the... the novel you've been working on".age:1}});function changeBio(newBio) {
    setState(current= > ({
      ...current,
      profile: {
        ...current.profile,
        bio: newBio
      }
    }));
  }
Copy the code

We can further simplify the Hooks example by replacing useState with useImmer Hook, and we can also update the React component by changing component state.

import { useImmer } from 'use-immer';

const [state, setState] = useImmer({
    id: 14.email: "[email protected]".profile: {
      name: "Stewie Griffin".bio: "You know, the... the novel you've been working on".age:1}});function changeBio(newBio) {
   setState(draft= > {
      draft.profile.bio = newBio;
    });
  }
Copy the code

Similarly, we can use Immer to convert arrays and Sets into immutable objects. Maps and sets created through Immer report errors when objects change, so that developers are aware of errors when objects change.

Most importantly, Immer isn’t limited to using React; you can also easily use Immer with native JavaScript.

In addition to maintaining immutability, Immer helps us maintain a well-written and readable code base by reducing its complexity.

This paper summarizes

Based on my experience with Immer, I believe that using Immer with React is a good choice. It simplifies project code and helps manage immutable state through design.

You can find out more about Immer in the reference documentation.

Thanks for reading!

If you find any mistakes in your translation or other areas that need to be improved, you are welcome to the Nuggets Translation Program to revise and PR your translation, and you can also get the corresponding reward points. The permanent link to this article at the beginning of this article is the MarkDown link to this article on GitHub.


The Nuggets Translation Project is a community that translates quality Internet technical articles from English sharing articles on nuggets. The content covers Android, iOS, front-end, back-end, blockchain, products, design, artificial intelligence and other fields. If you want to see more high-quality translation, please continue to pay attention to the Translation plan of Digging Gold, the official Weibo, Zhihu column.