Skip to content

Commit f88a214

Browse files
fix(android): always accumulate rawProps so un-flatten CREATE carries full props
Drop the earlier BackgroundStyleApplicator workaround — it targeted the wrong layer. Fix the actual root cause in Props::initializeDynamicProps. When a View with borderRadius + transparent backgroundColor mounts, Fabric flattens it and no Android View is created. On a later JS update such as backgroundColor -> opaque, the Differentiator sees the node un-flatten and emits a CREATE mutation for a brand-new native View. FabricMountingManager ships the props for that CREATE as newProps->rawProps. The problem: under the default (non-accumulated) path, Props::initialize overwrote rawProps with rawProps.toDynamic(filterObjectKeys) on every clone — storing only the latest JS diff, not the full accumulated state. So at un-flatten time, rawProps for the newly-concrete shadow node held only {backgroundColor: <color>} and the Android View received only that prop. borderRadius, borderWidth, etc. were never delivered, so the view rendered without them. The fix merges the previous rawProps with the incoming patch on every clone, so rawProps always reflects the full accumulated prop set. The existing getProps logic then ships the complete set on CREATE and the newly-created View gets every prop it should have. This was previously gated behind enableAccumulatedUpdatesInRawPropsAndroid. Always running it costs an extra folly::dynamic merge per clone but fixes a real correctness bug that could affect any view-flattening-prone component with more than one style prop.
1 parent a5bfcd6 commit f88a214

2 files changed

Lines changed: 14 additions & 14 deletions

File tree

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BackgroundStyleApplicator.kt

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -637,11 +637,7 @@ public object BackgroundStyleApplicator {
637637
compositeBackgroundDrawable.borderRadius,
638638
compositeBackgroundDrawable.borderInsets,
639639
)
640-
val newComposite = compositeBackgroundDrawable.withNewBackground(background)
641-
// Carry bounds over so the new BackgroundDrawable is primed with
642-
// the view's real size on first draw.
643-
newComposite.bounds = compositeBackgroundDrawable.bounds
644-
view.background = newComposite
640+
view.background = compositeBackgroundDrawable.withNewBackground(background)
645641
background
646642
}
647643
}

packages/react-native/ReactCommon/react/renderer/core/Props.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,19 @@ void Props::initializeDynamicProps(
7676
const Props& sourceProps,
7777
const RawProps& rawProps,
7878
const std::function<bool(const std::string&)>& filterObjectKeys) {
79-
if (ReactNativeFeatureFlags::enableAccumulatedUpdatesInRawPropsAndroid()) {
80-
auto& oldRawProps = sourceProps.rawProps;
81-
auto newRawProps = rawProps.toDynamic(filterObjectKeys);
82-
auto mergedRawProps = mergeDynamicProps(
83-
oldRawProps, newRawProps, NullValueStrategy::Override);
84-
this->rawProps = mergedRawProps;
85-
} else {
86-
this->rawProps = rawProps.toDynamic(filterObjectKeys);
87-
}
79+
// Always merge the previous rawProps with the incoming patch so that
80+
// `rawProps` reflects the full accumulated state for this shadow node.
81+
// Without this, a shadow node reconstructed from a subsequent JS update
82+
// only stores the latest prop diff in its rawProps. If the same shadow
83+
// node later un-flattens and the Differentiator emits a CREATE mutation
84+
// for it, FabricMountingManager::getProps ships only that partial diff
85+
// to Java — causing props like borderRadius to never reach the newly
86+
// created native view.
87+
auto& oldRawProps = sourceProps.rawProps;
88+
auto newRawProps = rawProps.toDynamic(filterObjectKeys);
89+
auto mergedRawProps =
90+
mergeDynamicProps(oldRawProps, newRawProps, NullValueStrategy::Override);
91+
this->rawProps = mergedRawProps;
8892
}
8993

9094
ComponentName Props::getDiffPropsImplementationTarget() const {

0 commit comments

Comments
 (0)