-
-
Notifications
You must be signed in to change notification settings - Fork 852
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Problem with recursive use #100
Comments
I'm not sure this problem is solvable without introducing confusion somewhere else. But if you could create a PR with some unit tests for this problem, that would be a start. We could for example opt to automatically finalize proxies that are passed as state to a producer. (after all, that instance shouldn't be edited anymore after passing it to a producer since you already produce a new state for it..) |
The issue might have been fixed by 1.1.3. Since this issue lacks a reproduction, now way to tell. Closing for now. Feel free to re-open with a reproduction if the issue isn't solved. |
Thank you @mweststrate! I'll report back once I have a look. |
Unfortunately, the bug appears to be still there, even after installing immer 1.1.3. I'll try to submit a reproduction, but this is unlikely to happen before a weekend that is 10 days from now. If anyone is fancy to build up a unit test out of my example above, feel free! The first code block should be sufficient. |
@mweststrate I was able to reproduce the bug in #118, feel free to have a look! Could you please reopen this issue? I don't have enough permissions to do so :–) |
Thanks for the clear test PR @kachkaev! I investigated a bit and the problem it exposes is that there are no clear semantics when passing a draft to another producers. For example: const textUpperCaser = produce(draft => {
draft.text = draft.text.toUpperCase()
})
const processor = produce(draft => {
draft.forEach((item, i) => {
draft[i] = textUpperCaser(item)
// Line X:
draft[i].count = 0 // Should this throw? or is it ok?
})
})
processor([{
text: "test",
count: 1
}]) The question is, what is the nature
There are few solutions to this:
const child = item.child
textUpperCase(item)
console.log(child.name) // throws! child is a revoked proxy because `item` was already finalized
To be continued :) |
Released as 1.3.0 |
Thank you @mweststrate! I upgraded to [email protected] and can confirm that I no longer experience the bug 🎉 |
@mweststrate You never stated which option you went with. Looks like you went with option 3, which has a notable side effect. Developers should never use I think the correct solution is to reuse the draft state's |
I have |
@mqklin please open new issues instead of commenting on old ones, and include details otherwise nobody will be able to help. But the premise itself is pretty simple, draft objects cannot be used once the producer function has ended. So if you get this error, you either are callign an async process from a producer, or you are storing references to the draft somewhere, which you shouldn't |
@mweststrate now I understand, thanks for the clarification. I'm not sure if the error is produced by |
I'm trying to call
produce
recursively to process a data tree, but am getting this exception in some cases:My guess is that
immer
unintentionally leaves some of the proxies behind and this is why the exception is triggered later in the code.Here's the original (broken) code, the goal of which is to replace all occurrences of
Date
ormoment
leafs into strings:Expected I/O example:
And here's a slightly clumsier version of the same module, but with no sub-calls of
produce
. It works:The broken version uses immer's
produce
recursively, which means that when a node in a tree is visited, the function's argument is an unfinalized Proxy, not a plain object. Although there exists an internal function calledfinalize
, I could not find how to import it. Can it be a solution for recursive calls?PS: My environment is node 9.5.0 (+TypeScript).
The text was updated successfully, but these errors were encountered: