Solomon Eseme I am a software developer who is geared toward building high-performing and innovative products following best practices and industry standards. I also love writing about it at masteringbackend.com. Follow me on Twitter @kaperskyguru, on Facebook, onLinkedIn, and on About.Me at Solomon Eseme." Follow me: Twitter, Facebook, LinkedIn, about.me

What’s new in Immer 7.0

2 min read 808

What's New in Immer 7.0?

Released on June 10, Immer 7.0 includes lots of new innovations, optimizations, and breaking changes. In this guide, we’ll look at what’s new in the latest release of Immer.

We’ll walk through some of the most impactful changes, including:

  • The introduction of current
  • getters and setters are now handled consistently
  • produce no longer accepts non-draftable objects as the first argument
  • original can only be called on drafts
  • Array patches computation

Let’s get started!

What is Immer?

Have you ever wanted to work with immutable state in JavaScript and ended up doing it in an inconvenient way or writing many lines of JavaScript code? Immer is a tiny package that allows you to work with immutable state in a more convenient way.

The basic idea is simple: Immer applies all your changes to a draft state, which is a proxy of the current state. Once you’re done changing/mutating the draft state, Immer produces the next state. That means your current state object is state from mutations and keeps all the benefits of immutability.

A working demo

Let’s walk through a simple demo.

Installation

First, upgrade to the latest version of Immer. At the time of writing, version 7.0.5 is the most current release.

yarn add immer
// OR
npm install immer

Open a JavaScript file and paste in the following.

import produce from "immer"
const todos = [ //baseState
  {
    text: “learn Immer”
    done: false
  }
  {
    text: “learn cookimg
    done: true
  }
]
const nextState = produce (todos, draftState) = {
  draftState.push ({text: “writing”, done: false})
  draftState[0].done = true
});
// Comparisons
console.log(todos === nextState) //false
console.log (todos[0].done === nextState[0].done) //false
console.log(todos[1].done === nextState[0].done) // true

The baseState will be untouched, but the nextState will be a new, immutable tree that reflects all changes made to draftState (and structurally shares the things that weren’t changed).

The above demo should give you a good sense of what Immer is all about. For more information, check out the documentation.

Now let’s dive into the latest updates.

5 key changes in Immer 7.0

Now let’s dive into the latest updates.

1. current method

Immer exposes a named export, current, that creates a copy of the current state of the draft. It takes a screenshot of the current state of a draft and finalizes it without freezing the object. This is a great utility for debugging the current state since those objects aren’t proxy objects.

Here’s an example:

const base = {
    x: 0
}

const next = produce(base, draft => {
    draft.x++
    const orig = original(draft)
    const copy = current(draft)
    console.log(orig.x)
    console.log(copy.x)

    setTimeout(() => {
        // this will execute after the produce has finised!
        console.log(orig.x)
        console.log(copy.x)
    }, 100)

    draft.x++
    console.log(draft.x)
})
console.log(next.x)

// This will print
// 0 (orig.x)
// 1 (copy.x)
// 2 (draft.x)
// 2 (next.x)
// 0 (after timeout, orig.x)
// 1 (after timeout, copy.x)

You can see the effect of the current method on the draft.

2. Getters and setters handled consistently

If you’ve ever used Immer with Vue or React and tried to work with classes, you’re familiar with the error it always generates:

// Immer drafts cannot have computed properties.

In Immer 7.0, this error is officially extinct. Owned getters are involved in the copy process, just like Object.assign would otherwise be.



You can read more about getters and setters in the docs.

3. Nondraftable objects

produce no longer accepts nondraftable objects as a first argument. Nondraftable objects are objects that are not JSON-serializable, such as the Date object in JavaScript (except when converted to strings).

Immer 7.0 doesn’t support this type of object and throws an exception when it encounters one.

4. Original can only be called on drafts

Have you ever tried to call original on objects that cannot be proxied and gotten stuck with that ugly undefined return type? For version 7, the Immer team added a catchable error to the original API, so instead of returning undefined, it throws an error.

5. Array patches computation

The patches for array are now computed differently to fix various scenarios in which they were incorrect. In some cases, they’re more optimal now; in
others, less so. For instance, splicing or unshifting items into an existing array might result in a lot of patches. In Immer 7.0, this is no longer an issue.

Conclusion

In this guide, we walked through some exciting new features and four breaking changes in Immer 7.0. Below is a list of additional bug fixes and breaking changes that fell outside the scope of this article.

Bug fixes

  1. All branches of the produced state should be frozen
  2. Inconsistent behavior with nested produce
  3. Does not work with polyfilled symbols
  4. Explicitly calling useProxies(false) shouldn’t check for the presence of proxy
  5. getownPropertyDescriptors unavailable in Internet Explorer or Hermes

Head to GitHub for a complete list of bug fixes.

Breaking changes

  1. Nonenumerable and symbolic fields will never be frozen

The GitHub repo has a complete list of breaking changes.

Are you adding new JS libraries to improve performance or build new features? What if they’re doing the opposite?

There’s no doubt that frontends are getting more complex. As you add new JavaScript libraries and other dependencies to your app, you’ll need more visibility to ensure your users don’t run into unknown issues.

LogRocket is a frontend application monitoring solution that lets you replay JavaScript errors as if they happened in your own browser so you can react to bugs more effectively.

https://logrocket.com/signup/

LogRocket works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store. 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 metrics like client CPU load, client memory usage, and more.

Build confidently — .

Solomon Eseme I am a software developer who is geared toward building high-performing and innovative products following best practices and industry standards. I also love writing about it at masteringbackend.com. Follow me on Twitter @kaperskyguru, on Facebook, onLinkedIn, and on About.Me at Solomon Eseme." Follow me: Twitter, Facebook, LinkedIn, about.me

Leave a Reply