Commit ca4ee56
fix(iOS): gate canBecomeFirstResponder behind enableImperativeFocus flag (#56366)
Summary:
Fixes a critical iOS regression introduced in RN 0.83 (#53825) where `RCTViewComponentView.canBecomeFirstResponder` unconditionally returns `YES`. This causes UIKit to promote parent views to first responder via `_promoteSelfOrDescendantToFirstResponderIfNecessary`, resulting in:
1. **TextInput autoFocus regression** — inputs lose focus on mount (focus→blur cycle)
2. **Keyboard reopening** — after any TextInput was focused/dismissed, opening native overlays (UIMenu, dropdown menus, header toolbar buttons) causes the keyboard to reappear unexpectedly
### Root Cause
PR #53825 added `canBecomeFirstResponder: YES` as part of the `enableImperativeFocus` feature, but didn't gate the return value behind the feature flag. When the flag is `false` (default), every `RCTViewComponentView` still claims first responder eligibility, causing UIKit's `_promoteSelfOrDescendantToFirstResponderIfNecessary` to steal focus from TextInputs.
Two distinct failure modes:
1. **On navigation transitions** — UIKit calls `_promoteSelfOrDescendantToFirstResponderIfNecessary` on the incoming screen's root view, walks the hierarchy, finds an `RCTViewComponentView` that returns `YES`, and promotes it — stealing focus from a TextInput that just called `becomeFirstResponder`.
2. **On native overlay dismissal** — When UIMenu/context menu/toolbar dismisses, UIKit restores first responder by walking to the nearest view claiming first responder eligibility, which is now every `RCTViewComponentView`.
### Fix
Gate `canBecomeFirstResponder` behind the `enableImperativeFocus` feature flag. When `false` (the default for all existing apps), views don't claim first responder — fixing the regression. When `true`, the imperative focus/blur feature works as designed.
This change is safe: `enableImperativeFocus` defaults to `false`, so the gated path only activates for apps explicitly opting in to the new focus/blur commands.
Credit to war-in for identifying this fix in #55908.
Fixes #55116
Related: expo/expo#43198, software-mansion/react-native-screens#3763, software-mansion/react-native-screens#3677
## Changelog:[iOS] [Fixed] - Gate RCTViewComponentView.canBecomeFirstResponder behind enableImperativeFocus flag to prevent keyboard reopening and focus theft in Fabric apps
Pull Request resolved: #56366
Test Plan:
1. Create a screen with a `TextInput` that has `autoFocus={true}`
2. Navigate to that screen using React Navigation (Stack)
3. Verify `TextInput` retains focus and keyboard stays visible — previously it would focus then immediately blur
4. Dismiss the keyboard, then open a native UIMenu or press a toolbar button
5. Verify keyboard does **NOT** reopen
6. Enable `enableImperativeFocus` flag, verify `focus()`/`blur()` commands still work on Views
> **Note:** This PR is intended as a backup to #55908 by war-in, which has the identical fix. If that PR gets reviewed and merged, this can be closed. Opening this to increase visibility on a critical regression affecting all RN 0.83+ iOS Fabric apps.
Reviewed By: cipolleschi
Differential Revision: D99994820
Pulled By: javache
fbshipit-source-id: bdfea2b01e43afa05e8cf35d12d9ccf7a56d63ca1 parent b1d12f5 commit ca4ee56
1 file changed
Lines changed: 1 addition & 1 deletion
Lines changed: 1 addition & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1721 | 1721 | | |
1722 | 1722 | | |
1723 | 1723 | | |
1724 | | - | |
| 1724 | + | |
1725 | 1725 | | |
1726 | 1726 | | |
1727 | 1727 | | |
| |||
0 commit comments