Skip to content

Commit df3f096

Browse files
rshestfacebook-github-bot
authored andcommitted
Always avoid setting default props on View component (remove reduceDefaultPropsInView feature flag) (facebook#52837)
Summary: Pull Request resolved: facebook#52837 # Changelog [Internal] - This feature has been enabled by default for a while, and has been proven to both not cause correctness issues, and also provide tangible performance improvements. We can remove the corresponding feature flag to improve code maintainability. Reviewed By: rubennorte Differential Revision: D78978302 fbshipit-source-id: 45cb865321f6e0eb449427845772fc522221514a
1 parent 01eaa6d commit df3f096

File tree

3 files changed

+82
-185
lines changed

3 files changed

+82
-185
lines changed

packages/react-native/Libraries/Components/View/View.js

Lines changed: 81 additions & 167 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
import type {ViewProps} from './ViewPropTypes';
1212

13-
import * as ReactNativeFeatureFlags from '../../../src/private/featureflags/ReactNativeFeatureFlags';
1413
import TextAncestorContext from '../../Text/TextAncestorContext';
1514
import ViewNativeComponent from './ViewNativeComponent';
1615
import * as React from 'react';
@@ -29,182 +28,97 @@ component View(
2928
) {
3029
const hasTextAncestor = use(TextAncestorContext);
3130

32-
let actualView;
33-
if (ReactNativeFeatureFlags.reduceDefaultPropsInView()) {
34-
const {
35-
accessibilityState,
36-
accessibilityValue,
37-
'aria-busy': ariaBusy,
38-
'aria-checked': ariaChecked,
39-
'aria-disabled': ariaDisabled,
40-
'aria-expanded': ariaExpanded,
41-
'aria-hidden': ariaHidden,
42-
'aria-label': ariaLabel,
43-
'aria-labelledby': ariaLabelledBy,
44-
'aria-live': ariaLive,
45-
'aria-selected': ariaSelected,
46-
'aria-valuemax': ariaValueMax,
47-
'aria-valuemin': ariaValueMin,
48-
'aria-valuenow': ariaValueNow,
49-
'aria-valuetext': ariaValueText,
50-
id,
51-
tabIndex,
52-
...otherProps
53-
} = props;
54-
55-
// Since we destructured props, we can now treat it as mutable
56-
const processedProps = otherProps as {...ViewProps};
57-
58-
const parsedAriaLabelledBy = ariaLabelledBy?.split(/\s*,\s*/g);
59-
if (parsedAriaLabelledBy !== undefined) {
60-
processedProps.accessibilityLabelledBy = parsedAriaLabelledBy;
61-
}
31+
const {
32+
accessibilityState,
33+
accessibilityValue,
34+
'aria-busy': ariaBusy,
35+
'aria-checked': ariaChecked,
36+
'aria-disabled': ariaDisabled,
37+
'aria-expanded': ariaExpanded,
38+
'aria-hidden': ariaHidden,
39+
'aria-label': ariaLabel,
40+
'aria-labelledby': ariaLabelledBy,
41+
'aria-live': ariaLive,
42+
'aria-selected': ariaSelected,
43+
'aria-valuemax': ariaValueMax,
44+
'aria-valuemin': ariaValueMin,
45+
'aria-valuenow': ariaValueNow,
46+
'aria-valuetext': ariaValueText,
47+
id,
48+
tabIndex,
49+
...otherProps
50+
} = props;
51+
52+
// Since we destructured props, we can now treat it as mutable
53+
const processedProps = otherProps as {...ViewProps};
54+
55+
const parsedAriaLabelledBy = ariaLabelledBy?.split(/\s*,\s*/g);
56+
if (parsedAriaLabelledBy !== undefined) {
57+
processedProps.accessibilityLabelledBy = parsedAriaLabelledBy;
58+
}
6259

63-
if (ariaLabel !== undefined) {
64-
processedProps.accessibilityLabel = ariaLabel;
65-
}
60+
if (ariaLabel !== undefined) {
61+
processedProps.accessibilityLabel = ariaLabel;
62+
}
6663

67-
if (ariaLive !== undefined) {
68-
processedProps.accessibilityLiveRegion =
69-
ariaLive === 'off' ? 'none' : ariaLive;
70-
}
64+
if (ariaLive !== undefined) {
65+
processedProps.accessibilityLiveRegion =
66+
ariaLive === 'off' ? 'none' : ariaLive;
67+
}
7168

72-
if (ariaHidden !== undefined) {
73-
processedProps.accessibilityElementsHidden = ariaHidden;
74-
if (ariaHidden === true) {
75-
processedProps.importantForAccessibility = 'no-hide-descendants';
76-
}
69+
if (ariaHidden !== undefined) {
70+
processedProps.accessibilityElementsHidden = ariaHidden;
71+
if (ariaHidden === true) {
72+
processedProps.importantForAccessibility = 'no-hide-descendants';
7773
}
74+
}
7875

79-
if (id !== undefined) {
80-
processedProps.nativeID = id;
81-
}
76+
if (id !== undefined) {
77+
processedProps.nativeID = id;
78+
}
8279

83-
if (tabIndex !== undefined) {
84-
processedProps.focusable = !tabIndex;
85-
}
80+
if (tabIndex !== undefined) {
81+
processedProps.focusable = !tabIndex;
82+
}
8683

87-
if (
88-
accessibilityState != null ||
89-
ariaBusy != null ||
90-
ariaChecked != null ||
91-
ariaDisabled != null ||
92-
ariaExpanded != null ||
93-
ariaSelected != null
94-
) {
95-
processedProps.accessibilityState = {
96-
busy: ariaBusy ?? accessibilityState?.busy,
97-
checked: ariaChecked ?? accessibilityState?.checked,
98-
disabled: ariaDisabled ?? accessibilityState?.disabled,
99-
expanded: ariaExpanded ?? accessibilityState?.expanded,
100-
selected: ariaSelected ?? accessibilityState?.selected,
101-
};
102-
}
84+
if (
85+
accessibilityState != null ||
86+
ariaBusy != null ||
87+
ariaChecked != null ||
88+
ariaDisabled != null ||
89+
ariaExpanded != null ||
90+
ariaSelected != null
91+
) {
92+
processedProps.accessibilityState = {
93+
busy: ariaBusy ?? accessibilityState?.busy,
94+
checked: ariaChecked ?? accessibilityState?.checked,
95+
disabled: ariaDisabled ?? accessibilityState?.disabled,
96+
expanded: ariaExpanded ?? accessibilityState?.expanded,
97+
selected: ariaSelected ?? accessibilityState?.selected,
98+
};
99+
}
103100

104-
if (
105-
accessibilityValue != null ||
106-
ariaValueMax != null ||
107-
ariaValueMin != null ||
108-
ariaValueNow != null ||
109-
ariaValueText != null
110-
) {
111-
processedProps.accessibilityValue = {
112-
max: ariaValueMax ?? accessibilityValue?.max,
113-
min: ariaValueMin ?? accessibilityValue?.min,
114-
now: ariaValueNow ?? accessibilityValue?.now,
115-
text: ariaValueText ?? accessibilityValue?.text,
116-
};
117-
}
101+
if (
102+
accessibilityValue != null ||
103+
ariaValueMax != null ||
104+
ariaValueMin != null ||
105+
ariaValueNow != null ||
106+
ariaValueText != null
107+
) {
108+
processedProps.accessibilityValue = {
109+
max: ariaValueMax ?? accessibilityValue?.max,
110+
min: ariaValueMin ?? accessibilityValue?.min,
111+
now: ariaValueNow ?? accessibilityValue?.now,
112+
text: ariaValueText ?? accessibilityValue?.text,
113+
};
114+
}
118115

119-
actualView =
120-
ref == null ? (
121-
<ViewNativeComponent {...processedProps} />
122-
) : (
123-
<ViewNativeComponent {...processedProps} ref={ref} />
124-
);
125-
} else {
126-
const {
127-
accessibilityElementsHidden,
128-
accessibilityLabel,
129-
accessibilityLabelledBy,
130-
accessibilityLiveRegion,
131-
accessibilityState,
132-
accessibilityValue,
133-
'aria-busy': ariaBusy,
134-
'aria-checked': ariaChecked,
135-
'aria-disabled': ariaDisabled,
136-
'aria-expanded': ariaExpanded,
137-
'aria-hidden': ariaHidden,
138-
'aria-label': ariaLabel,
139-
'aria-labelledby': ariaLabelledBy,
140-
'aria-live': ariaLive,
141-
'aria-selected': ariaSelected,
142-
'aria-valuemax': ariaValueMax,
143-
'aria-valuemin': ariaValueMin,
144-
'aria-valuenow': ariaValueNow,
145-
'aria-valuetext': ariaValueText,
146-
focusable,
147-
id,
148-
importantForAccessibility,
149-
nativeID,
150-
tabIndex,
151-
...otherProps
152-
} = props;
153-
const _accessibilityLabelledBy =
154-
ariaLabelledBy?.split(/\s*,\s*/g) ?? accessibilityLabelledBy;
155-
156-
const _accessibilityState =
157-
accessibilityState != null ||
158-
ariaBusy != null ||
159-
ariaChecked != null ||
160-
ariaDisabled != null ||
161-
ariaExpanded != null ||
162-
ariaSelected != null
163-
? {
164-
busy: ariaBusy ?? accessibilityState?.busy,
165-
checked: ariaChecked ?? accessibilityState?.checked,
166-
disabled: ariaDisabled ?? accessibilityState?.disabled,
167-
expanded: ariaExpanded ?? accessibilityState?.expanded,
168-
selected: ariaSelected ?? accessibilityState?.selected,
169-
}
170-
: undefined;
171-
172-
const _accessibilityValue =
173-
accessibilityValue != null ||
174-
ariaValueMax != null ||
175-
ariaValueMin != null ||
176-
ariaValueNow != null ||
177-
ariaValueText != null
178-
? {
179-
max: ariaValueMax ?? accessibilityValue?.max,
180-
min: ariaValueMin ?? accessibilityValue?.min,
181-
now: ariaValueNow ?? accessibilityValue?.now,
182-
text: ariaValueText ?? accessibilityValue?.text,
183-
}
184-
: undefined;
185-
186-
actualView = (
187-
<ViewNativeComponent
188-
{...otherProps}
189-
accessibilityLiveRegion={
190-
ariaLive === 'off' ? 'none' : ariaLive ?? accessibilityLiveRegion
191-
}
192-
accessibilityLabel={ariaLabel ?? accessibilityLabel}
193-
focusable={tabIndex !== undefined ? !tabIndex : focusable}
194-
accessibilityState={_accessibilityState}
195-
accessibilityElementsHidden={ariaHidden ?? accessibilityElementsHidden}
196-
accessibilityLabelledBy={_accessibilityLabelledBy}
197-
accessibilityValue={_accessibilityValue}
198-
importantForAccessibility={
199-
ariaHidden === true
200-
? 'no-hide-descendants'
201-
: importantForAccessibility
202-
}
203-
nativeID={id ?? nativeID}
204-
ref={ref}
205-
/>
116+
const actualView =
117+
ref == null ? (
118+
<ViewNativeComponent {...processedProps} />
119+
) : (
120+
<ViewNativeComponent {...processedProps} ref={ref} />
206121
);
207-
}
208122

209123
if (hasTextAncestor) {
210124
return (

packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -828,17 +828,6 @@ const definitions: FeatureFlagDefinitions = {
828828
},
829829
ossReleaseStage: 'none',
830830
},
831-
reduceDefaultPropsInView: {
832-
defaultValue: true,
833-
metadata: {
834-
dateAdded: '2025-5-12',
835-
description:
836-
'Optimize how default (accessibility) props are processed in View to avoid unnecessary keys.',
837-
expectedReleaseValue: true,
838-
purpose: 'experimentation',
839-
},
840-
ossReleaseStage: 'none',
841-
},
842831
shouldUseAnimatedObjectForTransform: {
843832
defaultValue: false,
844833
metadata: {

packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<4a82f02f08467a26ec38ec44d21484cf>>
7+
* @generated SignedSource<<1f567a382688ca9876d17e9ce8d428ff>>
88
* @flow strict
99
* @noformat
1010
*/
@@ -35,7 +35,6 @@ export type ReactNativeFeatureFlagsJsOnly = $ReadOnly<{
3535
enableAccessToHostTreeInFabric: Getter<boolean>,
3636
fixVirtualizeListCollapseWindowSize: Getter<boolean>,
3737
isLayoutAnimationEnabled: Getter<boolean>,
38-
reduceDefaultPropsInView: Getter<boolean>,
3938
shouldUseAnimatedObjectForTransform: Getter<boolean>,
4039
shouldUseRemoveClippedSubviewsAsDefaultOnIOS: Getter<boolean>,
4140
shouldUseSetNativePropsInFabric: Getter<boolean>,
@@ -150,11 +149,6 @@ export const fixVirtualizeListCollapseWindowSize: Getter<boolean> = createJavaSc
150149
*/
151150
export const isLayoutAnimationEnabled: Getter<boolean> = createJavaScriptFlagGetter('isLayoutAnimationEnabled', true);
152151

153-
/**
154-
* Optimize how default (accessibility) props are processed in View to avoid unnecessary keys.
155-
*/
156-
export const reduceDefaultPropsInView: Getter<boolean> = createJavaScriptFlagGetter('reduceDefaultPropsInView', true);
157-
158152
/**
159153
* Enables use of AnimatedObject for animating transform values.
160154
*/

0 commit comments

Comments
 (0)