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:
current
getters
and setters
are now handled consistentlyproduce
no longer accepts non-draftable objects as the first argumentoriginal
can only be called on draftsLet’s get started!
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.
Let’s walk through a simple demo.
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.
Now let’s dive into the latest updates.
current
methodImmer 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
.
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.
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.
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.
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.
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.
produce
useProxies(false)
shouldn’t check for the presence of proxygetownPropertyDescriptors
unavailable in Internet Explorer or HermesHead to GitHub for a complete list of bug fixes.
The GitHub repo has a complete list of breaking changes.
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.
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 — start monitoring for free.
Leptos is an amazing Rust web frontend framework that makes it easier to build scalable, performant apps with beautiful, declarative UIs.
Learn more about the 5 best JavaScript libraries for dealing with multidimensional arrays, such as ndarray, math.js, and NumJs.
We spoke with Dom about his approach to balancing innovation with handling tech debt and to learn how he stays current with technology.
Vite is a versatile, fast, lightweight build tool with an exceptional DX. Let’s explore when and why you should adopt Vite in your projects.