You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This issue is related to this reanimated issue, but I think it should be solved/discussed here.
High-level overview
The issue is that if we have a commit hook, that clones some nodes in the ShadowTree, applied on a commit that changes the c++ state of a ShadowNode, then this c++ state update will get lost.
More detailed description
The best way to describe this issue is to show an example. Let's say we have the following tree:
Now let's say our commit hook want's to do some work on SomeView. Then it has to clone it (also Parent has to be cloned, as we don't really know in the commit hook if the Parent can be modified in place). This is what it should look like:
This is because when we clone the Parent, this line is hit, causing adoptYogaChild (here) to be called for every child. In adoptYogaChild there is a check that determines whether we have to clone the given child. For CustomComponentWithState it decides that it has to be cloned (even though it has never been commited to any revision). The clone call there passes empty ShadowNodeFragment causing the default value to be used, which is sourceShadowNode.getMostRecentState() - so the last mounted state. That's why the new state gets lost.
Repro explanation
I created a repro for iOS on a separate branch in rn-tester. The repro doesn't include reanimated, I just added a simple commit hook, and modified a bit the sample custom component to showcase the lost state update.
I use the changeColor function to trigger a state update. In the logs you can see how the state update is triggered, commit hook is called and an unsealed SampleNativeComponentShadowNode gets cloned, but no state update is received on the native side.
If we change the clone call in adoptYogaChild, to use the source node state, the state update will come.
I don't think that's a proper solution, because I think we shouldn't be cloning this node altogether as it is not sealed, but I don't fully understand the connection between yogaNodes and ShadowNodes, so I don't know what the fix here would be.
Description
This issue is related to this reanimated issue, but I think it should be solved/discussed here.
High-level overview
The issue is that if we have a commit hook, that clones some nodes in the
ShadowTree, applied on a commit that changes the c++ state of aShadowNode, then this c++ state update will get lost.More detailed description
The best way to describe this issue is to show an example. Let's say we have the following tree:
flowchart TD A[Parent⁰] B[ViewWithState⁰ <br /> state=0] C[SomeView⁰] A-->B A-->CLet's say there is a state update, that changes state from 0 to 1. Before the commit hook is called we have (ViewWithState and Parent got cloned):
flowchart TD A[Parent ¹] B[ViewWithState¹ <br /> state=1] C[SomeView⁰] A-->B A-->CNow let's say our commit hook want's to do some work on
SomeView. Then it has to clone it (alsoParenthas to be cloned, as we don't really know in the commit hook if theParentcan be modified in place). This is what it should look like:flowchart TD A[Parent²] B[ViewWithState¹ <br /> state=1] C[SomeView²] A-->B A-->CBut actually what happens is this:
flowchart TD A[Parent²] B[ViewWithState² <br /> **state=0**] C[SomeView²] A-->B A-->CThis is because when we clone the
Parent, this line is hit, causingadoptYogaChild(here) to be called for every child. InadoptYogaChildthere is a check that determines whether we have to clone the given child. ForCustomComponentWithStateit decides that it has to be cloned (even though it has never been commited to any revision). The clone call there passes emptyShadowNodeFragmentcausing the default value to be used, which issourceShadowNode.getMostRecentState()- so the last mounted state. That's why the new state gets lost.Repro explanation
I created a repro for iOS on a separate branch in rn-tester. The repro doesn't include reanimated, I just added a simple commit hook, and modified a bit the sample custom component to showcase the lost state update.
I use the
changeColorfunction to trigger a state update. In the logs you can see how the state update is triggered, commit hook is called and an unsealedSampleNativeComponentShadowNodegets cloned, but no state update is received on the native side.If we change the
clonecall inadoptYogaChild, to use the source node state, the state update will come.I don't think that's a proper solution, because I think we shouldn't be cloning this node altogether as it is not sealed, but I don't fully understand the connection between
yogaNodesandShadowNodes, so I don't know what the fix here would be.Steps to reproduce
React Native Version
main
Affected Platforms
The reproduction is for iOS, but this is mostly related to the
ShadowTreestate update pipeline, so should be applicable to any platform.Areas
Fabric - The New Renderer
Reproducer
https://github.com/bartlomiejbloniarz/react-native/tree/%40bartlomiejbloniarz/commit-hook-repro
Screenshots and Videos
No response