refactor: use Immer for immutable state updates#527
Conversation
| @@ -1,5 +1,6 @@ | |||
| { | |||
| "lockfileVersion": 1, | |||
| "configVersion": 0, | |||
There was a problem hiding this comment.
Not sure what I did wrong here, first time using bun.
| if (extractingModels.size > 0) { | ||
| if (extractingModels.size === 1) { | ||
| const [modelId] = Array.from(extractingModels); | ||
| const extractingKeys = Object.keys(extractingModels); |
There was a problem hiding this comment.
This is the only place where I feel I hurt readability, instead of improving it, but I find the original code to not be the most readable. I can make more PRs. We should add the tests first.
| "model-extraction-started", | ||
| (event) => { | ||
| const modelId = event.payload; | ||
| setExtractingModels((prev) => new Set(prev.add(modelId))); |
There was a problem hiding this comment.
🟢 The "correct" old pattern would have been:
const myNewSet = new Set(myOldSet)
// mutate myNewSet
🔴 But instead, the old code did this:
// mutate myOldSet
return new Set(myOldSet)
This is illustrative. This isn't stylistic. This is correctness.
|
What I wonder about this: is it possible to just have a similar fix without adding a new dependency here? I'm okay to add the dependency for what it's worth because I know |
|
Hey @cjpais there are potentially a few paths forward here:
Usually in my experience attempts to resist Immer and continue using immutability can start to lead to ... less than ideal patterns. I can empathize with the pain of adding a dependency though. If immutability or react were abandoned in the future, would this change make the code more portable? |
|
ooh. i like this PR. think its pretty close to what i've been working on here #478 not to derail the conversation, but think your insight would be super helpful to get this over the finish line, since ive been relying on zustand |
|
Thanks for the extra detail @joshribakoff I'll probably pull this in soon enough but this is definitely not going to happen
|
|
@joshribakoff would you mind rebasing the code to main, I removed |
|
Fair enough on vueJS opposition, just answering what the alternatives are, my preference would also be React (with the caveat that it has footguns and i recommend using immerJs). Ill get this rebased shortly. |
Replace Set/Map with Record types and use Immer's produce() for immutable state updates. This fixes mutation bugs where .add()/.set() were mutating state before copying (e.g., `new Set(prev.add(id))`). Changes: - Add immer dependency - Convert Set<string> to Record<string, true> (sparse hash set pattern) - Convert Map<K,V> to Record<K,V> - Use produce() for all state mutations - Update prop types in child components 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
f50893d to
e696e72
Compare
|
It looks like Zuststand, which you've added a dependency on, also uses Immerjs under the hood, if you use certain parts of the lib. I have resolved the merge conflict with rebase, as requested. |
|
thank you, merged! |
Before Submitting This PR
Please confirm you have done the following:
Human Written Description
The old code:
I will backfill missing automated tests, in separate PRs as discussed
See remaining AI generated description below.
Related Issues/Discussions
#525
Testing
Typescript compiles (I'd be confident on this alone, for these small changes).
Rust compiles
Compiled Tauri app runs
GUI manual smoke test seems fine to me.
Replace Set/Map with Record types and use Immer's produce() for immutable state updates. This fixes mutation "bugs" where .add()/.set() were mutating state before copying (e.g.,
new Set(prev.add(id))).Changes:
🤖 Generated with Claude Code