From 21fcb933ae416205d38de19dedea1d211124e971 Mon Sep 17 00:00:00 2001 From: bintangakbarRK Date: Tue, 4 Aug 2026 15:16:25 +0700 Subject: [PATCH] fix(iOS): re-apply Selected/NotEnabled traits after role change on recycled views When accessibilityTraits changes (role change), the writer replaces the full bitmask without Selected/NotEnabled. On a recycled view, if accessibilityState hasn't changed (stale props match new props), the state writer skips and the Selected trait is permanently lost. Re-apply the state bits (Selected/NotEnabled) from the current accessibilityState immediately after overwriting the role traits. This is idempotent when the state writer also fires. Fixes #57515 --- .../ComponentViews/View/RCTViewComponentView.mm | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index d13cd8a600a..b0f75131286 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -488,6 +488,17 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared & if (oldViewProps.accessibilityTraits != newViewProps.accessibilityTraits) { self.accessibilityElement.accessibilityTraits = RCTUIAccessibilityTraitsFromAccessibilityTraits(newViewProps.accessibilityTraits); + // Re-apply Selected/NotEnabled from the current accessibilityState. The traits + // writer replaces the full bitmask (from role), which doesn't include state bits. + // On a recycled view, accessibilityState may not have changed (so its writer below + // won't fire), but the traits were just overwritten and need the state bits re-applied. + const auto accessibilityState = newViewProps.accessibilityState.value_or(AccessibilityState{}); + if (accessibilityState.selected) { + self.accessibilityTraits |= UIAccessibilityTraitSelected; + } + if (accessibilityState.disabled) { + self.accessibilityTraits |= UIAccessibilityTraitNotEnabled; + } } // `accessibilityState`