From bd7ab6c90b6eae84f50ff4f3bb62f4edf4df0831 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Wed, 4 Nov 2020 08:08:26 -0800 Subject: [PATCH] Fabric: Introducing `YogaLayoutableKindMutatesStylesAfterCloning` trait Summary: This implements a new ShadowNode trait that helps to propagate Yoga node `isDirty` flag down the root of the tree and clone siblings appropriately. Several Fabric components mutate its Yoga styles after the node was cloned. In such cases, we need to mark the node as dirty after doing so. The problem with this is that the parent node and its siblings were already updated (cloned or not) based on the previous value of the `isDirty` flag. This happens because this logic is implemented in YogaLayoutableShadowNode which is a base constructor that must be called before any other logic from a subclass can run. For now, this change enables that for SafeAreaView only (which seems to help with some junkiness issues), later we can extend the usage of this for other components if needed. Changelog: [Internal] Fabric-specific internal change. Reviewed By: JoshuaGross Differential Revision: D24719347 fbshipit-source-id: b0d050afea5de9c470e05e1b4c9e7052e00ae949 --- .../components/safeareaview/SafeAreaViewShadowNode.h | 8 ++++++++ .../renderer/components/view/YogaLayoutableShadowNode.cpp | 5 +++++ ReactCommon/react/renderer/core/ShadowNodeTraits.h | 6 ++++++ 3 files changed, 19 insertions(+) diff --git a/ReactCommon/react/renderer/components/safeareaview/SafeAreaViewShadowNode.h b/ReactCommon/react/renderer/components/safeareaview/SafeAreaViewShadowNode.h index 1bd4e47e62e..2c1e0c7fa5d 100644 --- a/ReactCommon/react/renderer/components/safeareaview/SafeAreaViewShadowNode.h +++ b/ReactCommon/react/renderer/components/safeareaview/SafeAreaViewShadowNode.h @@ -26,6 +26,14 @@ class SafeAreaViewShadowNode final : public ConcreteViewShadowNode< ViewEventEmitter, SafeAreaViewState> { using ConcreteViewShadowNode::ConcreteViewShadowNode; + + public: + static ShadowNodeTraits BaseTraits() { + auto traits = ConcreteViewShadowNode::BaseTraits(); + traits.set( + ShadowNodeTraits::Trait::YogaLayoutableKindMutatesStylesAfterCloning); + return traits; + } }; } // namespace react diff --git a/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp b/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp index 60f867e1ee0..4b4fee2b47e 100644 --- a/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp +++ b/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp @@ -82,6 +82,11 @@ YogaLayoutableShadowNode::YogaLayoutableShadowNode( static_cast(sourceShadowNode) .yogaNode_.isDirty() == yogaNode_.isDirty()); + if (getTraits().check(ShadowNodeTraits::Trait:: + YogaLayoutableKindMutatesStylesAfterCloning)) { + yogaNode_.setDirty(true); + } + if (fragment.props) { updateYogaProps(); } diff --git a/ReactCommon/react/renderer/core/ShadowNodeTraits.h b/ReactCommon/react/renderer/core/ShadowNodeTraits.h index 16b7129bd00..d4b663406ca 100644 --- a/ReactCommon/react/renderer/core/ShadowNodeTraits.h +++ b/ReactCommon/react/renderer/core/ShadowNodeTraits.h @@ -54,6 +54,12 @@ class ShadowNodeTraits { // Nodes with this trait (and all their descendants) will not produce views. Hidden = 1 << 6, + // Indicates that the `YogaLayoutableShadowNode` must set `isDirty` flag for + // Yoga node when a `ShadowNode` is being cloned. `ShadowNode`s that modify + // Yoga styles in the constructor (or later) *after* the `ShadowNode` + // is cloned must set this trait. + YogaLayoutableKindMutatesStylesAfterCloning = 1 << 7, + // Inherits `YogaLayoutableShadowNode` and enforces that the `YGNode` is a // leaf. LeafYogaNode = 1 << 10,