Immutability in React with Immer
Tags: react, javascript, webdev
Published: 2020-03-25 13:57:10

---
title: Immutability in React with Immer
published: true
date: 2020-03-06 17:00:25 UTC
tags: react,javascript,webdev
canonical_url: https://blog.logrocket.com/immutability-in-react-with-immer/
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/mkkyj47dme2uiiphy8xg.png
---
**Written by [Leonardo Maldonado](https://blog.logrocket.com/author/leonardomaldonado/)**✏️

We know that JavaScript is a dynamically, multi-paradigm, weakly typed language. This means that we can apply a lot of different paradigms in our JavaScript code, we can have, for example, object-oriented JavaScript, imperative JavaScript, functional programming JavaScript, etc. A lot of JavaScript developers started to adopt the functional programming paradigm in their applications.

A few libraries were created, and now that the adoption of React is expanding and growing massively among developers, the immutability concept is starting to be used and discussed more often as well. Let’s first understand what immutability is and then we’ll look at how we can use this concept of functional programming in our React applications.

## Immutability

In a functional programming language, one of the most interesting and important concepts is immutability. The whole meaning of immutability is “unable to change”, if we have an object and want to create a new object, we should copy the actual object and not mutate it.

When creating applications we need to think about the user and, more importantly, the user data. All the data that’s created, modified, deleted, and replaced in your application is important and should be watched, stored, and managed properly. That’s why we should create better standards or concepts to deal with our data.

But why should we have an immutable code in our application? Well, we can use immutability to benefit in some points, for example:

- **Readability**—  if you have an immutable code, your application will get more readable for you and your team, it’ll get easier to understand exactly what’s happening and what every piece of code is performing
- **Maintainability**—  with an immutable code, your application will get a lot easier to debug and maintain, when errors happen — and this is something we cannot avoid easily, they always happen — it will get very easy to find where it happened and where things went wrong
- **Fewer side effects**—  this could be a more positive point for maintainability, but when you have an immutable code, the chances to have negative side effects in your application decreases. You will end up with more manageable code, and the chances to have unexpectable errors in your applications decreases

[![LogRocket Free Trial Banner](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/f760c-1gpjapknnuyhu8esa3z0jga.png?resize=1200%2C280&ssl=1)](https://logrocket.com/signup/)

## Immutability in React

In React applications, the most important parts of your application is the state data. You should care and manage it properly, otherwise, it will cause bugs and you will lose data very easily, which can be your worst nightmare.

It’s well known by React developers that we should not mutate our state directly, but use the `setState` method. But why?

This is one of the main ideas behind React — track changes and if something changes, rerender the component. You cannot simply change your state mutably, because it’ll not trigger a rerender in your component. By using the `setState` method, you will create a new state in an immutable way, React will know that something changed, and will rerender the respective component.

We also have similar behavior in Redux, the most famous and used state management library for React applications. Redux represents the state as immutable objects, to change your state you should pass your new state data using pure functions, these pure functions are called `reducers`. Reducers should never mutate the state, to avoid side effects in your application, and make sure that Redux keeps track of the current state data.

We can see that the concept of immutability is getting used more and becoming more common in the React community. But to make sure that we’re doing it the right way, we can use a library for the job.

## Immer

To better deal with state data, a library was created to help us, called Immer. [Immer](https://immerjs.github.io/immer/docs/introduction) was created to help us to have an immutable state, it’s a library created based on the [“copy-on-write” mechanism](https://www.computerhope.com/jargon/c/copy-on-write.htm) — a technique used to implement a copy operation in on modifiable resources.

Immer is very easy to understand, this is how Immer works:

1. You have your actual state data
2. Immer will copy your actual state data, and create a new temporary “draft” of it. This draft will be a proxy of the next state data
3. After the draft is created, Immer will update your state data with the draft, which is a proxy of your next state data
4. To simplify, this is how Immer will deal with your state:

![how Immer deals with state](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2020/03/statedraft.png?resize=730%2C185&ssl=1)

## Getting started

To start using Immer, you need first to install it:

```jsx
yarn add immer
```

Now we’re going to import Immer inside our component. The library exports a default function called `produce`:

```jsx
produce(currentState, producer: (draftState) => void): nextState
```

The first argument of the `produce` function is our current state object, the second argument is a function, which will get our `draft` state and then perform the changes that we want to.

Let’s create a simple component called `Users` and we’ll make a list of users. We’ll create a simple state called `users`, which will be an array of users, and another state called `users` which will be an object. Inside that object, we’ll have the `name` of the `user`:

```jsx
this.state = {
  user: {
    name: "",
  },
  users: []
}
```

Now, let’s import the `produce` function from Immer and create a new function called `onInputChange`. Every time we type on the input, we’ll change the value of the `name` of the `user`.

```jsx
onInputChange = event => {
  this.setState(produce(this.state.user, draftState => {
    draftState.user = {
      name: event.target.value
    }
  }))
}
```

The `setState` method from React accepts a function, so we’re passing the `produce` function from Immer, inside the `produce` function we’re passing as a first argument our `user` state, and as a second argument, we’re using a function. Inside that function, we’re changing our `draftState` of `user` to be equal to the input value. So, we’re tracking the value of the input and saving it on our `user` state.

Now that we’re saving our user state correctly, let’s submit a new user every time we click on the button. We’ll create a new function called `onSubmitUser`, and our function is going to look like this:

```jsx
onSubmitUser = () => {
  this.setState(produce(draftState => {
    draftState.users.push(this.state.user);
    draftState.user = {
      name: ""
    }
  }))
}
```

You can notice now that we’re using the `setState` again, passing our `produce` function, but now we’re only using the `draftState` as an argument, and we are no longer using the current state as an argument. But why?

Well, Immer has something called [curried producers](https://immerjs.github.io/immer/docs/curried-produce), if you pass a function as the first argument to your `produce` function, it’ll be used for currying. We have a “curried” function now, which means that this function will accept a state, and call our updated draft function.

So, in the end, our whole component will look like this:

```jsx
class Users extends Component {
  constructor(props) {
    super(props);
    this.state = {
      user: {
        name: ""
      },
      users: []
    };
  }

  onInputChange = event => {
    this.setState(
      produce(this.state.user, draftState => {
        draftState.user = {
          name: event.target.value
        };
      })
    );
  };

  onSubmitUser = () => {
    this.setState(
      produce(draftState => {
        draftState.users.push(this.state.user);
        draftState.user = {
          name: ""
        };
      })
    );
  };

  render() {
    const { users, user } = this.state;
    return (
      <div>
        <h1>Immer with React</h1>
        {users.map(user => (
          <h4>{user.name}</h4>
        ))}
        <input type="text" value={user.name} onChange={this.onInputChange} />
        <button onClick={this.onSubmitUser}>Submit</button>
      </div>
    );
  }
}
```

Now that we created our example using Immer with class components, you might be asking is it possible to use Immer with React Hooks? Yes, it is!

## useImmer Hook

The `useImmer` Hook is pretty similar to the `useState` Hook from React. First, let’s install it:

```jsx
yarn add use-immer
```

Let’s create a new component called `UserImmer`, inside that component we’re going to import the `useImmer` Hook from `use-immer`:

```jsx
import React from 'react';
import { useImmer } from "use-immer";

const UserImmer = () => {
  ...
}
export default UserImmer;
```

We’re going to have two states in our component. We’ll have `users` for our list of users, and `user`:

```jsx
const [user, setUser] = useImmer({
  name: ''
})
const [users, setUsers] = useImmer([])
```

Now, let’s create a function with the same name as the previous example, `onInputChange`, and inside that function, we’re going to update the value of our `user`:

```jsx
const onInputChange = (user) => {
  setUser(draftState => {
    draftState.name = user
  })
}
```

Let’s now create our `onSubmitUser` function, which will add a new user every time we click on the button. Pretty similar to the previous example:

```jsx
const onSubmitUser = () => {
  setUsers(draftState => {
    draftState.push(user)
  })

  setUser(draftState => {
    draftState.name = ""
  })
}
```

You can see that we’re using both `setUsers` and `setUser` function. We’re using the `setUsers`function first to add the `user` to our `users` array. After that, we’re using the `setUser` function just to reset the value of the `name` of the `user` to an empty string.

Our whole component will look like this:

```jsx
import React from 'react';
import { useImmer } from "use-immer";
const UserImmer = () => {
  const [user, setUser] = useImmer({
    name: ''
  })
  const [users, setUsers] = useImmer([])
  const onInputChange = (user: any) => {
    setUser(draftState => {
      draftState.name = user
    })
  }
  const onSubmitUser = () => {
    setUsers(draftState => {
      draftState.push(user)
    })
    setUser(draftState => {
      draftState.name = ""
    })
  }
  return (
    <div>
      <h1>Users</h1>
      {users.map((user, index) => (
        <h5 key={index}>{user.name}</h5>
      ))}
      <input
        type="text"
        onChange={e => onInputChange(e.target.value)}
        value={user.name}
      />
      <button onClick={onSubmitUser}>Submit</button>
    </div>
  )
}
export default UserImmer;
```

We have now a component using Immer with an immutable state. This is very easy to start, easier to maintain, and our code gets a lot more readable. If you’re planning to start with immutability in React and want to make your state immutable and safer, Immer is your best option.

Another thing that might be important for you to know is you can use Immer not only with React but with plain JavaScript as well. So, if you’re going to build a simple application using vanilla JavaScript, and you want to have an immutable state, you can use Immer very easily. In the long-term, it will help you a lot to have a more confident, well-written, and maintainable application.

## Conclusion

In this article, we learned about immutability in React and how we can use Immer to have an immutable state — making our application safer, readable, and maintainable. To learn more about Immer, you can check out its [documentation](https://immerjs.github.io/immer/docs/introduction), and if you want to learn more about this fantastic library, you can take this [course](https://egghead.io/courses/immutable-javascript-data-structures-with-immer).

* * * 
## Full visibility into production React apps 

Debugging React applications can be difficult, especially when users experience issues that are difficult to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, [try LogRocket.](https://www2.logrocket.com/react-performance-monitoring)

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/eq752g8qhbffxt3hp9t4.png)

[LogRocket](https://www2.logrocket.com/react-performance-monitoring) is like a DVR for web apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — [start monitoring for free.](https://www2.logrocket.com/react-performance-monitoring)
* * *

The post [Immutability in React with Immer](https://blog.logrocket.com/immutability-in-react-with-immer/) appeared first on [LogRocket Blog](https://blog.logrocket.com).