HackerReposA FIELD GUIDE TO OPEN SOURCE
ProSponsor the shelf♧ 0
← Back to top all-time
immerjs
immer
JavaScript2018–2025
immerjs / immer

immer

Create the next immutable state by mutating the current one

22Distinct people
28Mentions
1Explicit recommenders
29KGitHub stars
REPOSITORY AT A GLANCE

What to know before exploring

What it is

Create the next immutable state by mutating the current one

GitHub

Where it is used

No documented product use was verified in the last source check.

What people are saying

Hi, I'm a Redux maintainer. I personally would recommend _against_ using Immutable.js, for a number of reasons [0]. Instead, I highly recommend the Immer library [1], which…

acemarke used a recommendation phrase. One indexed comment matches. This is a phrase match, not a verdict.

No classified warning is attached to this page. Read the discussions before treating silence as approval.

Also in these discussions

Mentioned in the same Hacker News threads. That is not proof they are substitutes.

This week on Hacker News

Nov 7–Nov 14 UTC · Direct repository links and separately labeled related project stories. Indexed through 11/14/2026, 11:56:56 AM UTC.

No direct repository links were found in the indexed HN discussions over the past seven days. Older discussions are available below.

Mentions over time

HN mentions by year28 dated mentions

Observed mentions: 2018-01-01 19:34:07 UTC to 2025-12-25 16:13:03 UTC.

02468102018-01-01 00:00:00 UTC to 2019-01-01 00:00:00 UTC (exclusive): 9 mentions; 3 submissions, 6 comments20182019-01-01 00:00:00 UTC to 2020-01-01 00:00:00 UTC (exclusive): 9 mentions; 0 submissions, 9 comments2020-01-01 00:00:00 UTC to 2021-01-01 00:00:00 UTC (exclusive): 4 mentions; 0 submissions, 4 comments2021-01-01 00:00:00 UTC to 2022-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments20212022-01-01 00:00:00 UTC to 2023-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2023-01-01 00:00:00 UTC to 2024-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments2024-01-01 00:00:00 UTC to 2025-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2025-01-01 00:00:00 UTC to 2026-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2025

Counts come from the repository’s dated source evidence. Index cutoff: 2026-11-02 08:16:59 UTC.

View mention counts and date ranges
UTC ranges include their start and exclude their end. Select a period to filter the source evidence.
PeriodStart (UTC)End (exclusive, UTC)MentionsSubmissionsComments
20182018-01-01 00:00:00 UTC2019-01-01 00:00:00 UTC936
20192019-01-01 00:00:00 UTC2020-01-01 00:00:00 UTC909
20202020-01-01 00:00:00 UTC2021-01-01 00:00:00 UTC404
20212021-01-01 00:00:00 UTC2022-01-01 00:00:00 UTC202
20222022-01-01 00:00:00 UTC2023-01-01 00:00:00 UTC101
20232023-01-01 00:00:00 UTC2024-01-01 00:00:00 UTC202
20242024-01-01 00:00:00 UTC2025-01-01 00:00:00 UTC000
20252025-01-01 00:00:00 UTC2026-01-01 00:00:00 UTC101

What Hacker News says

28 sources
I've never seen this kind of benchmark graph before, and it looks really neat! How was this generated? What tool was used for the benchmarks? (I actually spent most of Sep/Oct working on optimizing the Immer JS immutable update library, and used a benchmarking tool called `mitata`, so I was doing a lot of this same kind of work: https://github.com/immerjs/immer/pull/1183 . Would love to add some new tools to my repertoire here!)
In Python 3.15’s interpreter for Windows x86-64 should hopefully be 15% faster
Thanks! Cami is technically a combination of both. I like the intuitiveness of observables so that’s used: ``` // define observable this.count = this.observable(0); // getting this.count.value; // setting this.count.update(value => value + 1); ``` But it also has a redux-like pattern where you can dispatch actions and register reducers with far less ceremony: ``` // define store const todoStore = createStore({ todos: [], }); // register reducer / producer todoStore.register('add', (store, payload) => { store.todos.push(payload); }); // subscribe component to store this.todos = this.subscribe(todoStore, 'todos'); // dispatch this.dispatch("add", newTodo); ``` It looks like it’s mutating, but both the reducers and update() uses immer* under the hood, so we still respect immutability under the hood. Cami supports redux devtools s
Read the rest
o you can use that for time-travel debugging too. —- * https://github.com/immerjs/immer
In Show HN: Cami.js – A no build, web component based reactive framework
This is basically what Immer [0] does for Javascript apps if you use immutable-like libraries like Redux which expect a new object created every time a property changes so that it can detect that it's changed and propagate that to any observing components. Perhaps Haskell needs something similar. [0] https://github.com/immerjs/immer
In Lenses
Hi! Great questions :) First of all, SyncedStore does not implement any CRDT algorithms. Credits for this go to Yjs [1] (and its author Kevin), which it uses as underlying CRDT. Yjs and Automerge are (afaik) the two most commonly used CRDT implementations. Both have their pros and cons, but Yjs has focused a lot on performance [2]. Automerge has a bit friendlier "Immer style" [3] API. I'm not too familiar with @localfirst/state, but it seems to add a Redux style API on top of Automerge. My approach with SyncedStore was really to provide an API on top of Yjs that's as simple as possible to use in React / Vue / Svelte or plain JS app. I.e.: only use a single React Hook to observe changes, and use regular Javascript assigments to update values. The API is inspired mostly by Reactive Programming libraries such as MobX [4] (from the same autho
Read the rest
r as Immer). Hope you're still following along :) Maybe it helps to compare the TODO-MVC applications, as both SyncedStore (https://github.com/YousefED/SyncedStore/tree/main/examples) and @localfirst/state (https://github.com/local-first-web/state/tree/main/examples/...) have implemented these as examples! [1]: https://github.com/yjs/yjs [2]: https://github.com/dmonad/crdt-benchmarks [3]: https://github.com/immerjs/immer [4]: https://mobx.js.org/
In Show HN: SyncedStore CRDT – build multiplayer collaborative apps for React / Vue
To me, it is lazy to use immutable data structures in situations where they generate large amounts of garbage and/or result in user-facing GC pauses. (In Firefox, I encounter many slow sites (with or without immutability) with multi-frame pauses, often GC pauses. I think the slowdown is coming from the website and not my extensions.) I believe it's possible to understand the code you create, even in the presence of mutation (though you can no longer store old values for free, and need to use cloning or other approaches). You need to restrict which code is responsible for mutating state (using careful program architecture), and restrict the ability to mutate data while other pointers to the data exist (Rust imposes these restrictions). Interestingly, the Relm architecture is a translation of the Elm architecture (Elm is an immutable langua
Read the rest
ge) to Rust code (Rust is a mutable language) which restricts which code is responsible for mutating state, and Rust restricts the ability to mutate data while other pointers to the data exist. Interestingly, Rust unifies immutable and mutable data structures. The im library (https://docs.rs/im) uses the same tree-based immutable data structures as Clojure and such, but exposes an API closer to Rust's stdlib containers (including mutation). However im's performance characteristics are different from Rust's stdlib; clones are shallow and take O(1) time, while IndexMut is slower and copies tree nodes whenever that node's refcount is greater than 1. immer.js (https://github.com/immerjs/immer) has a somewhat similar API, but a different implementation (I think it uses standard JS arrays and copies the whole thing when you mutate one element).
In 4x Smaller, 50x Faster
I'd recommend caution when adopting redux-toolkit in large & rapidly-evolving projects. I recently (2 months back) moved a medium sized project (~240 branch reducers, ~600 actions) away from redux-toolkit. My primary complaint is that the recommended setup doesn't work well with changing requirements where we often have to move away from branch-local state handling to something that needs access to wider state. We started out with a number of slices and our reducer logic was local to these slices and used only the state within that slice. However as our application evolved, for processing a number of these actions (which were previously slice-local) we needed access to state from other branches. So now we had a couple of options: A. Dispatch thunks instead of actions: This gets ugly real fast because now your action handling logic is spli
Read the rest
t across thunks & reducers, and is hard to follow. This also needs refactoring across every dispatch site. B. Use something like redux sagas to intercept actions: We found this to be "too" flexible and felt that we were better-off without the entire machinery of spawning sagas on the fly. We wanted it to be easy to reason about what happens when an action is dispatched looking at the code without having to debug what all sagas could be running at that particular point of time. C. Move the action handling higher up: requires extensively refactoring the reducers. The solution we settled on was redux-loop [1]: A port of elm's effect system to redux. This was neat because we could easily convert the reducer to return loops instead of states, and thereby easily get access to full state and dispatch while retaining the ability to follow through the complete action handling flow from a single starting point that didn't change. TypeScript support in redux-toolkit is also kind'a bolted on and users are recommended different approaches when they care about type-safety. It proved to be a pain to communicate junior devs multiple times that you should use leave the reducers as empty object and instead use "extraReducers" with builder API. We found using immer[2] (for managing immutable state) and unionize[3] (for handling discriminated union of action types) directly to be a much better solution than redux-toolkit's abstractions. [1]: https://github.com/redux-loop/redux-loop [2]: https://github.com/immerjs/immer [3]: https://www.npmjs.com/package/unionize
In Learn Functional Programming Design from Redux
I was looking at EnTT's API when building a little toy ECS of my own in JavaScript. Since I'm working in JS, I haven't really tried to copy its internal architecture since it doesn't quite make sense for a higher-level GC'd runtime, but I think the public API was a really handy reference for the kinds of things a practical ECS needs to have. It's a really impressive and robust project, and the documentation is super thorough and worth a peek if you have any interest in game architecture. (slightly off-topic, but I'm excited to have a venue to ramble a bit about this:) ECS is really cool, and I'm excited about using it more for my games. The "cheap" (de)serialization by moving all state into pure, data-only components is really fascinating - I've been playing around with building networked multiplayer games for a while now, and I'm current
Read the rest
ly experimenting with rollback netcode. A key part of rollback is saving your state every frame so you can load it if you need to roll back, and ECS makes saving/loading easier to reason about, since you can "just" grab the components and their associated entity IDs and load if needed (EnTT, for the record, has an API for this[1], though they leave the actual (de)serialization up to you). Of course, JS's lack of a memcpy equivalent makes this much harder than what you could do in C++, which has lead me to experiment with immer[2] in my ECS, which uses structural sharing to avoid mutation, so you can get a "copy" of your state by just keeping a reference to it, as future updates will make new objects. This, of course, theoretically could make a ton of garbage (e.g. updating your position every frame would create a new Position object every frame), which is not great for high performance games. I'm not sure how bad this will be in practice - JS GC is relatively smart and fast these days, but I haven't tried doing much beyond little pong or platformer demos yet. I'd also imagine that, like, doing a deep clone of my state tree every frame (or doing the whole JSON.stringify/parse dance if I stick to primitive values) probably generates just as much garbage. Maybe if I could integrate immer with some kind of object pool it'd avoid these issues, but I have no idea how useful object pooling is in practice in JS... [1] https://github.com/skypjack/entt/wiki/Crash-Course:-entity-c... [2] https://github.com/immerjs/immer
In EnTT: Gaming meets Modern C++
acemarke·May 23, 2019Recommendation phrase
Hi, I'm a Redux maintainer. I personally would recommend _against_ using Immutable.js, for a number of reasons [0]. Instead, I highly recommend the Immer library [1], which lets you do immutable updates with "mutating" logic in callbacks. Even better, try out our new Redux Starter Kit package. It uses Immer internally to let you simplify immutable updates in your reducers [2]. [0] https://www.reddit.com/r/javascript/comments/4rcqpx/dan_abra... [1] https://github.com/immerjs/immer [2] https://redux-starter-kit.js.org/
In JavaScript Array.push is 945x faster than Array.concat
To properly embrace immutable.js and not have performance issues, you need to fully embrace it and it's API and use it as the basis for all of the models in your app. We did a half-baked approach which uses immutables in the data store (so we can leverage quick prop checks) but also convert those into normal JS objects in the business domain. This makes our use of it noticeably slow. Immer [0] is a much better alternative IMO.. you get all the benefits of immutability without having to use a radically different API than normal. And the performance is roughly the same as immutable. And using it with Redux is natural [1], removing the need to do a bunch of nested object copies [0] https://github.com/immerjs/immer [1] https://daveceddia.com/react-redux-immutability-guide/#easy-...
In Why I don't use React

Showing the 15 most recent of 28 sources. Enable JavaScript to search and browse every indexed mention.

MAKE YOURSELF AT HOME

A few shortcuts

/
Search the collection
?
Open this guide
Esc
Close dialogs and navigation

Your saved repositories and interests stay in this browser.