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
A recycled Fabric iOS view can lose the Selected accessibility trait after reuse.
On Fabric iOS, self.accessibilityTraits is written by two places in RCTViewComponentView updateProps:
accessibilityTraits: replaces the full bitmask from the role (does not include Selected)
accessibilityState: ORs in Selected/NotEnabled
Both writers diff against the view's retained props. Retained props survive recycling, so a recycled view diffs new props against stale values from its previous lifecycle.
Example with three lifecycles of one recycled view:
Button A (role=button, selected=true): both writers fire. Traits = Button | Selected. ✅
Button A again (role=button, selected=true): the role changed (none → button), so the traits writer fires and sets Button. But retained props still hold selected=true from lifecycle 1, so the state writer skips. Traits = Button only. Selected is lost. ❌
Steps to reproduce
Render two Views with different keys and different roles (role="button" and no role), both with accessibilityState={{ selected: true }}
Conditionally render one at a time; toggle between them so Fabric unmounts one and mounts the other (forcing the native view through the recycle pool)
Focus the recycled View in Accessibility Inspector
The Selected trait is missing
The bug fires when the recycled view's stale _props.selected matches the new value (true → true), so the accessibilityState diff guard skips.
Reproducer Steps
git clone https://github.com/cgoldsby/rn-accessibility-traits-bug.git
cd rn-accessibility-traits-bug
yarn install
cd ios && pod install &&cd ..
yarn ios
Open Accessibility Inspector
Focus the target View
Tap "Toggle Role" to switch from role="button" to no role (both selected: true)
Accessibility Inspector shows the Selected trait is lost
React Native Version
0.86.0
Affected Platforms
Runtime - iOS
Output of npx @react-native-community/cli info
info Fetching system and libraries information...
System:
OS: macOS 26.4.1
CPU: (8) arm64 Apple M1
Memory: 148.58 MB / 16.00 GB
Shell:
version: "5.9"
path: /bin/zsh
Binaries:
Node:
version: 20.19.6
path: ~/.nvm/versions/node/v20.19.6/bin/node
Yarn:
version: 1.22.22
path: /opt/homebrew/bin/yarn
npm:
version: 10.8.2
path: ~/.nvm/versions/node/v20.19.6/bin/npm
Watchman:
version: 2025.05.26.00
path: /opt/homebrew/bin/watchman
Managers:
CocoaPods:
version: 1.15.2
path: /Users/cgoldsby/.rbenv/shims/pod
SDKs:
iOS SDK:
Platforms:
- DriverKit 25.5
- iOS 26.5
- macOS 26.5
- tvOS 26.5
- visionOS 26.5
- watchOS 26.5
Android SDK:
API Levels:
- "31"
- "33"
- "34"
- "35"
- "36"
- "37"
Build Tools:
- 30.0.3
- 31.0.0
- 33.0.0
- 33.0.1
- 34.0.0
- 35.0.0
- 36.0.0
- 37.0.0
System Images:
- android-31 | Android TV ARM 64 v8a
- android-31 | AOSP ATD ARM 64 v8a
- android-33 | Android TV ARM 64 v8a
- android-34 | Android TV ARM 64 v8a
- android-34 | Google TV ARM 64 v8a
- android-34 | Google APIs ARM 64 v8a
- android-35 | Google Play ARM 64 v8a
Android NDK: Not Found
IDEs:
Android Studio: 2025.2 AI-252.25557.131.2521.14344949
Xcode:
version: 26.5/17F42
path: /usr/bin/xcodebuild
Languages:
Java:
version: 17.0.10
path: /usr/bin/javac
Ruby:
version: 4.0.2
path: /Users/cgoldsby/.rbenv/shims/ruby
npmPackages:
"@react-native-community/cli": Not Found
react:
installed: 19.2.3
wanted: 19.2.3
react-native: Not Found
react-native-macos: Not Found
npmGlobalPackages:
"*react-native*": Not Found
Android:
hermesEnabled: Not found
newArchEnabled: Not found
iOS:
hermesEnabled: Not found
newArchEnabled: Not found
Description
A recycled Fabric iOS view can lose the
Selectedaccessibility trait after reuse.On Fabric iOS,
self.accessibilityTraitsis written by two places inRCTViewComponentView updateProps:accessibilityTraits: replaces the full bitmask from the role (does not includeSelected)accessibilityState: ORs inSelected/NotEnabledBoth writers diff against the view's retained props. Retained props survive recycling, so a recycled view diffs new props against stale values from its previous lifecycle.
Example with three lifecycles of one recycled view:
Button | Selected. ✅None. ✅Button. But retained props still holdselected=truefrom lifecycle 1, so the state writer skips. Traits =Buttononly.Selectedis lost. ❌Steps to reproduce
role="button"and no role), both withaccessibilityState={{ selected: true }}Selectedtrait is missingThe bug fires when the recycled view's stale
_props.selectedmatches the new value (true → true), so theaccessibilityStatediff guard skips.Reproducer Steps
role="button"to no role (bothselected: true)Selectedtrait is lostReact Native Version
0.86.0
Affected Platforms
Runtime - iOS
Output of
npx @react-native-community/cli infoStacktrace or Logs
MANDATORY Reproducer
https://github.com/cgoldsby/rn-accessibility-traits-bug
Screenshots and Videos
reproducer.mp4