I think this one might be a bit obscure, and there's a few workarounds, but it appears to be a newly introduced bug so thought it might be important to record it for you guys in case any related issues crop up. Not sure if it should be in this repo or the core immer repo, but I can only recreate it with use-immer. My real-world case is a lot more complex than this, but I've tried to get the example as simple as possible.
I have a library project, built with microbundle, that has a custom hook
The custom hook uses useImmer
There is a function inside the custom hook that makes a nested call to produce (i.e. draft of a draft), in this case increasing the age of person2 (increaseAgePerson2Nested)
The library is imported into a separate create-react-appapp - use npm run start to try it out
The hook is used inside the app, and the function is called, which causes immer to throw an exception:
// Firefox
Uncaught TypeError: source is undefined
peek proxy.ts:238
set proxy.ts:146
node_modules bundle.js:380
produce immerClass.ts:94
...
// Chrome
Uncaught TypeError: Cannot read properties of undefined (reading 'age')
at peek (proxy.ts:238:1)
at Object.set (proxy.ts:146:1)
at index.ts:44:1
at Immer.produce (immerClass.ts:94:1)
...
I've added a few more test cases in there that don't cause the exception. They match the labels of the buttons in the app, in approximate order of weirdness:
Use useState instead of useImmer, and make nested calls to produce in library - ✓ works
Using the same useImmer instance that has the bug...
2b Expose the mutation method and perform the mutation in the app codebase instead of the library - ✓ works
2c No nested call to produce, increment the age by mutating the first draft in the library - ✓ works
Same as 1, but also freeze the initial state so it's basically a carbon copy of the actual code from useImmer - ✓ works
Nested mutation, absolutely identical to 2, which causes the bug. but the useImmer & mutation code is in the app component instead of the library - ✓ works
(no example) Downgrade immer from 9.0.13 to 9.0.12, despite 9.0.13 looking like it just changed a type definition and some documentation - ✓ works
I don't really understand the internals of immer, but it looked like some sort of global state wasn't being handled properly, so I converted everything in the library to a peer dependency just to make sure there weren't two versions of anything, but this didn't have any effect.
Edit: I'm using use-immer 0.7.0, which is odd, because the package.json and release history in GH suggest the latest is 0.6.1... I'm having a very weird week.
I think this one might be a bit obscure, and there's a few workarounds, but it appears to be a newly introduced bug so thought it might be important to record it for you guys in case any related issues crop up. Not sure if it should be in this repo or the core immer repo, but I can only recreate it with
use-immer
. My real-world case is a lot more complex than this, but I've tried to get the example as simple as possible.useImmer
produce
(i.e. draft of a draft), in this case increasing the age of person2 (increaseAgePerson2Nested
)create-react-app
app - usenpm run start
to try it outI've added a few more test cases in there that don't cause the exception. They match the labels of the buttons in the app, in approximate order of weirdness:
useState
instead ofuseImmer
, and make nested calls toproduce
in library - ✓ worksuseImmer
instance that has the bug...produce
, increment the age by mutating the first draft in the library - ✓ worksuseImmer
- ✓ worksuseImmer
& mutation code is in the app component instead of the library - ✓ worksI don't really understand the internals of immer, but it looked like some sort of global state wasn't being handled properly, so I converted everything in the library to a peer dependency just to make sure there weren't two versions of anything, but this didn't have any effect.
Edit: I'm using
use-immer
0.7.0, which is odd, because the package.json and release history in GH suggest the latest is 0.6.1... I'm having a very weird week.