ITADN

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

#57515Opencgoldsby 创建于 2026-07-10
Platform: iOSNeeds: Triage :mag:
C
cgoldsbycommented
### 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 ```sh 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` ```text N/A ``` ### Stacktrace or Logs ```text N/A ``` ### MANDATORY Reproducer https://github.com/cgoldsby/rn-accessibility-traits-bug ### Screenshots and Videos https://github.com/user-attachments/assets/3047debb-477d-44bd-88d6-7c9bd5ffff72
0 条评论