Skip to content

[iOS][Fabric] A recycled Fabric iOS view can lose the Selected accessibility trait after reuse #57514

Description

@cgoldsby

Description

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:

  1. Button A (role=button, selected=true): both writers fire. Traits = Button | Selected. ✅
  2. Plain view (role=none, selected=false): both writers fire. Traits = None. ✅
  3. 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

  1. Render two Views with different keys and different roles (role="button" and no role), both with accessibilityState={{ selected: true }}
  2. 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)
  3. Focus the recycled View in Accessibility Inspector
  4. 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

N/A

Stacktrace or Logs

N/A

MANDATORY Reproducer

https://github.com/cgoldsby/rn-accessibility-traits-bug

Screenshots and Videos

reproducer.mp4

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions