The Rise of Immer in React

The need for immutability in JavaScript isn't obvious. Classically, the primary advantage of immutability is fearless concurrency, but as JavaScript is single-threaded it isn't much of a benefit.

The history of immutability in React can be traced as far back as December 2013 when David Nolen first introduced Om. Om was a wrapper around React for ClojureScript users to be able to use it, but the weird thing about Om was that it turned out to be faster than React.

How can a wrapper over a thing be faster than the thing itself? David did a great talk about it here but the primary reason is immutable data. The bulk of React's work is reconciliation, and it turns out that you can skip a lot of it if you can shallow compare objects and arrays and memoize functions. React Fiber's data structure effectively does a lot of memoization under the hood to avoid repeat work.

Despite its downsides, Immer not only fulfills both of these requirements, but is also lightweight, simple, and generally performant. Thus far, developers enjoy using Immer; it has been extremely non-intrusive and easy to uptake with little-to-no learning curve. — Workday Engineering

react-copy-write uses @mweststrate's Immer internally. It lets you mutate a draft of an object to process an immutable update. Since this uses structural-sharing, react-copy-write is very good about only re-rendering when it needs to — Brandon Dail

and the React team:

"If you like MobX, I highly recommend following along @mweststrate’s work on Immer. While MobX is pretty far removed from the vision of where we’re going with React. Immer is dead on." — Sebastian Markbåge

So there is something obviously magic going on with Immer and it is worth spending some time thinking about how Immer's philosophy may fit particularly well with React's principles to understand what is going on.

When it comes to understanding React's philosophy (as separate from React the library as it exists today) there are two documents I constantly refer to: the Design Principles on the official docs and react-basic, a pseudocode progression through core beliefs in React. I'll highlight three concepts relevant to Immer:

The biggest issue with Immutable.js is the difficulty of interoperability. Although we have been happy users of Immutable.js at Netlify over 2 years, we get constant reminders we are not using "just JavaScript" every time we try to destructure Immutable.js Maps:

This is the same philosophy that led to React's success as well — React's focus on interoperability allowed gradual adoption (instead of having to convert everything everywhere at once) as well as the general ability to work with other libraries in the JavaScript ecosystem that assume data structures passed to them are plain JS. This is the same goal pitched by Brendan Eich back when proxies were introduced around 2010. Immer is a great use case for unobtrusively extending the language!

Debugging

Immer's advanced Patches feature allows opportunities for fine-grained debugging and tracing, potentially even building developer tools on top of it.

As a nice bonus, Patches also allow for Redux-like undo/redo implementations to be done without too much ceremony. Please see the linked resources for code as full examples are too long to be included here.

My confession to you is that I've been slowly walking you through this mental framework as you read through this article. I think it is a great way to evaluate technologies and also explain why some open source projects gain greater adoption in some communities than others.

Immer's meteoric rise is notable, but it is not without reason — it comes from a lot of historical learning and has already gained a great following within the React community, and none of it would be possible if it didn't get its fundamental philosophy right.

Dan Abramov also noted recently how these cycles of evolution in technology go, and how people break paradigms successfully:

Recipe for success: take something that’s easy to debug, and make it less annoying to write. Thanks to @mweststrate for immer! — Dan Abramov

I think this is a profound insight — Immer would not have been possible if prior art hadn't already established the core developer experience benefit of immutability, making the remaining problem the leaky API. Immer thus focuses on keeping the same benefits while improving the API in the same ways that made React successful.

The best way to incrementally try Immer today is in reducing your Redux or React setState boilerplate. In the future, look for many more Immer-powered libraries like the highly anticipated redux-starter-kit project as well as non-Redux state-management solutions like react-copy-write, immer-wieder and bey for building fast, boilerplate-free apps!