From cfb6c968ddce56138553a9d2e0cc8dfc666eb943 Mon Sep 17 00:00:00 2001 From: Peter Abbondanzo Date: Mon, 16 Jun 2025 12:05:47 -0700 Subject: [PATCH] Mark hasTVPreferredFocus as deprecated (#52043) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/52043 The `hasTVPreferredFocus` prop is functionally similar to the `focusable` prop. On iOS, the props are identical. The primary difference appears on Android, where the prop attempts to request focus when set to true. Attempting to invoke imperative API calls through declarative means has been [a source of confusion](https://github.com/react-native-tvos/react-native-tvos/issues/237) and we should instead recommend requesting focus through imperative means, like calling `focus()` on a specific view's ref instead. Workarounds presented rely on lifecycle methods to request focus natively. This change only marks these methods as deprecated on JS. In the following version, they will be removed from the public API. Changelog: [General][Deprecated] - Deprecate `hasTVPreferredFocus` Reviewed By: andrewdacenko Differential Revision: D76732539 fbshipit-source-id: 64912b4dacb76cd40e79148c1082d8ed8f573879 --- packages/react-native/Libraries/Components/Button.js | 1 + .../Libraries/Components/Touchable/TouchableHighlight.js | 3 +++ .../Libraries/Components/Touchable/TouchableNativeFeedback.js | 1 + .../Libraries/Components/Touchable/TouchableOpacity.d.ts | 1 + .../Libraries/Components/Touchable/TouchableOpacity.js | 1 + .../react-native/Libraries/Components/View/ViewPropTypes.d.ts | 4 ++++ .../react-native/Libraries/Components/View/ViewPropTypes.js | 1 + 7 files changed, 12 insertions(+) diff --git a/packages/react-native/Libraries/Components/Button.js b/packages/react-native/Libraries/Components/Button.js index 7824947d761..2b944380e1f 100644 --- a/packages/react-native/Libraries/Components/Button.js +++ b/packages/react-native/Libraries/Components/Button.js @@ -63,6 +63,7 @@ export type ButtonProps = $ReadOnly<{ @platform tv @default false + @deprecated Use `focusable` instead */ hasTVPreferredFocus?: ?boolean, diff --git a/packages/react-native/Libraries/Components/Touchable/TouchableHighlight.js b/packages/react-native/Libraries/Components/Touchable/TouchableHighlight.js index 6d81eead72b..338d6c99744 100644 --- a/packages/react-native/Libraries/Components/Touchable/TouchableHighlight.js +++ b/packages/react-native/Libraries/Components/Touchable/TouchableHighlight.js @@ -30,6 +30,9 @@ type AndroidProps = $ReadOnly<{ }>; type IOSProps = $ReadOnly<{ + /** + * @deprecated Use `focusable` instead + */ hasTVPreferredFocus?: ?boolean, }>; diff --git a/packages/react-native/Libraries/Components/Touchable/TouchableNativeFeedback.js b/packages/react-native/Libraries/Components/Touchable/TouchableNativeFeedback.js index 4de3b0c790b..481c9adf257 100644 --- a/packages/react-native/Libraries/Components/Touchable/TouchableNativeFeedback.js +++ b/packages/react-native/Libraries/Components/Touchable/TouchableNativeFeedback.js @@ -29,6 +29,7 @@ type TVProps = { * *(Apple TV only)* TV preferred focus (see documentation for the View component). * * @platform ios + * @deprecated Use `focusable` instead */ hasTVPreferredFocus?: ?boolean, diff --git a/packages/react-native/Libraries/Components/Touchable/TouchableOpacity.d.ts b/packages/react-native/Libraries/Components/Touchable/TouchableOpacity.d.ts index bd72669a22c..d579a8d66b1 100644 --- a/packages/react-native/Libraries/Components/Touchable/TouchableOpacity.d.ts +++ b/packages/react-native/Libraries/Components/Touchable/TouchableOpacity.d.ts @@ -16,6 +16,7 @@ export interface TVProps { * *(Apple TV only)* TV preferred focus (see documentation for the View component). * * @platform ios + * @deprecated Use `focusable` instead */ hasTVPreferredFocus?: boolean | undefined; diff --git a/packages/react-native/Libraries/Components/Touchable/TouchableOpacity.js b/packages/react-native/Libraries/Components/Touchable/TouchableOpacity.js index 8bba7ab1467..d2db6e3b918 100644 --- a/packages/react-native/Libraries/Components/Touchable/TouchableOpacity.js +++ b/packages/react-native/Libraries/Components/Touchable/TouchableOpacity.js @@ -26,6 +26,7 @@ export type TVProps = $ReadOnly<{ * *(Apple TV only)* TV preferred focus (see documentation for the View component). * * @platform ios + * @deprecated Use `focusable` instead */ hasTVPreferredFocus?: ?boolean, diff --git a/packages/react-native/Libraries/Components/View/ViewPropTypes.d.ts b/packages/react-native/Libraries/Components/View/ViewPropTypes.d.ts index b52feb743be..62803cabce7 100644 --- a/packages/react-native/Libraries/Components/View/ViewPropTypes.d.ts +++ b/packages/react-native/Libraries/Components/View/ViewPropTypes.d.ts @@ -21,6 +21,9 @@ import { import {Touchable} from '../Touchable/Touchable'; import {AccessibilityProps} from './ViewAccessibility'; +/** + * @deprecated These properties are not implemented natively. + */ export interface TVViewPropsIOS { /** * *(Apple TV only)* When set to true, this view will be focusable @@ -34,6 +37,7 @@ export interface TVViewPropsIOS { * *(Apple TV only)* May be set to true to force the Apple TV focus engine to move focus to this view. * * @platform ios + * @deprecated Use `focusable` instead */ hasTVPreferredFocus?: boolean | undefined; diff --git a/packages/react-native/Libraries/Components/View/ViewPropTypes.js b/packages/react-native/Libraries/Components/View/ViewPropTypes.js index 2347f4f31bb..a5b02b22166 100644 --- a/packages/react-native/Libraries/Components/View/ViewPropTypes.js +++ b/packages/react-native/Libraries/Components/View/ViewPropTypes.js @@ -280,6 +280,7 @@ export type ViewPropsAndroid = $ReadOnly<{ * Whether to force the Android TV focus engine to move focus to this view. * * @platform android + * @deprecated Use `focusable` instead */ hasTVPreferredFocus?: ?boolean,