immerjs / immer

Create the next immutable state by mutating the current one

Home Page:https://immerjs.github.io/immer/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Is pre-freezing manually a good way to deal with circular references?

user72356 opened this issue · comments

I'm forced to deal with a complex data structure that has circular references. This is an array of array of objects. In each object I have plain properties and a reference to another object, which somewhere deep has a circular reference to itself. I'm adding new rows/columns to this array of array within a producer.

As it is, I'm getting a "Immer forbids circular references" error.

If I deep pre-freeze the whole thing manually before the producer using freeze(data, true), it works fine. Alternatively I can be a little more fine-grained by looping through the data just to shallow pre-freeze the object causing the circular reference, and then call the producer. It works too.

The questions: how is pre-freezing the object helping with the circular references? Is there a mechanism in Immer that recognizes that an object is frozen and that skips following a reference? What is the performance implication of shallow freezing many object, or deep-freezing the entire data structure? Is this the best way to deal with circular references?

I didn't find a documentation page on this topic but I found this interesting discussion that put me on this path: #465 (comment)

Did I miss the documentation for this behavior?

Circular references are fundamentally incompatible with the paradigm in which Immer is used, so I'd consider redesigning it. That being said, the alternative is indeed to not apply Immer to parts of the tree indeed. The normal thing to do here is set [immerable] to false on the object / class: https://immerjs.github.io/immer/complex-objects.

Freezing does work as well, because frozen objects won't be post-processed (Immer won't look for changes there, or try to freeze it again), but only to the extend that you didn't access nor modify those objects in your producer. If you access / change the object, it will still break. Shallow freezing is very efficient, I wouldn't worry about it, but again the idiomatic solution is setting immerable to false.