Skip to content

Commit 78f69d0

Browse files
committed
Feature Flag for React.jsx` "spreading a key to jsx" warning
Adds a feature flag for when React.jsx warns you about spreading a key into jsx. It's false for all builds, except as a dynamic flag for fb/www. I also made it so it warns at most once per component name, and included the name in the warning.
1 parent 4d9f850 commit 78f69d0

11 files changed

+40
-8
lines changed

packages/react/src/ReactElementValidator.js

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
REACT_FRAGMENT_TYPE,
2222
REACT_ELEMENT_TYPE,
2323
} from 'shared/ReactSymbols';
24+
import {warnAboutSpreadingKeyToJSX} from 'shared/ReactFeatureFlags';
2425
import checkPropTypes from 'prop-types/checkPropTypes';
2526

2627
import ReactCurrentOwner from './ReactCurrentOwner';
@@ -268,6 +269,9 @@ function validateFragmentProps(fragment) {
268269
}
269270
}
270271

272+
// warn about spreading keys to an element only once per ComponentName
273+
const didWarnAboutSpreadingKey = {};
274+
271275
export function jsxWithValidation(
272276
type,
273277
props,
@@ -365,13 +369,20 @@ export function jsxWithValidation(
365369
}
366370
}
367371

368-
if (hasOwnProperty.call(props, 'key')) {
369-
if (__DEV__) {
370-
console.error(
371-
'React.jsx: Spreading a key to JSX is a deprecated pattern. ' +
372-
'Explicitly pass a key after spreading props in your JSX call. ' +
373-
'E.g. <ComponentName {...props} key={key} />',
374-
);
372+
if (__DEV__) {
373+
if (warnAboutSpreadingKeyToJSX) {
374+
if (hasOwnProperty.call(props, 'key')) {
375+
const name = getComponentName(type) || 'ComponentName';
376+
if (didWarnAboutSpreadingKey[name] !== true) {
377+
didWarnAboutSpreadingKey[name] = true;
378+
console.error(
379+
'React.jsx: Spreading a key to JSX is a deprecated pattern. ' +
380+
'Explicitly pass a key after spreading props in your JSX call. ' +
381+
'E.g. <%s {...props} key={key} />',
382+
name,
383+
);
384+
}
385+
}
375386
}
376387
}
377388

packages/react/src/__tests__/ReactElementJSX-test.internal.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ describe('ReactElement.jsx', () => {
3232

3333
ReactFeatureFlags = require('shared/ReactFeatureFlags');
3434
ReactFeatureFlags.enableJSXTransformAPI = true;
35+
ReactFeatureFlags.warnAboutSpreadingKeyToJSX = true;
3536

3637
React = require('react');
3738
ReactDOM = require('react-dom');
@@ -371,7 +372,11 @@ describe('ReactElement.jsx', () => {
371372
expect(() => ReactDOM.render(React.jsx(Parent, {}), container)).toErrorDev(
372373
'Warning: React.jsx: Spreading a key to JSX is a deprecated pattern. ' +
373374
'Explicitly pass a key after spreading props in your JSX call. ' +
374-
'E.g. <ComponentName {...props} key={key} />',
375+
'E.g. <Child {...props} key={key} />',
376+
);
377+
// does not warn twice for the same component
378+
expect(() => ReactDOM.render(React.jsx(Parent, {}), container)).toErrorDev(
379+
[],
375380
);
376381
});
377382

packages/shared/ReactFeatureFlags.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ export const disableJavaScriptURLs = false;
4848
// Control this behavior with a flag to support 16.6 minor releases in the meanwhile.
4949
export const exposeConcurrentModeAPIs = __EXPERIMENTAL__;
5050

51+
// Warns when a combination of updates on a dom can cause a style declaration
52+
// that clashes with a previous one https://github.com/facebook/react/pull/14181
5153
export const warnAboutShorthandPropertyCollision = true;
5254

5355
// Experimental React Flare event system and event components support.
@@ -106,8 +108,14 @@ export const runAllPassiveEffectDestroysBeforeCreates = false;
106108
// WARNING This flag only has an affect if used with runAllPassiveEffectDestroysBeforeCreates.
107109
export const deferPassiveEffectCleanupDuringUnmount = false;
108110

111+
// Use this flag to generate "testing" builds, that include APIs like act()
112+
// and extra warnings/errors
109113
export const isTestEnvironment = false;
110114

115+
// Enables a warning when trying to spread a 'key' to an element;
116+
// a deprecated pattern we want to get rid of in the future
117+
export const warnAboutSpreadingKeyToJSX = false;
118+
111119
// --------------------------
112120
// Future APIs to be deprecated
113121
// --------------------------

packages/shared/forks/ReactFeatureFlags.native-fb.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export const disableUnstableCreatePortal = false;
5555
export const deferPassiveEffectCleanupDuringUnmount = false;
5656
export const runAllPassiveEffectDestroysBeforeCreates = false;
5757
export const isTestEnvironment = false;
58+
export const warnAboutSpreadingKeyToJSX = false;
5859

5960
// Only used in www builds.
6061
export function addUserTimingListener() {

packages/shared/forks/ReactFeatureFlags.native-oss.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export const disableUnstableCreatePortal = false;
5050
export const deferPassiveEffectCleanupDuringUnmount = false;
5151
export const runAllPassiveEffectDestroysBeforeCreates = false;
5252
export const isTestEnvironment = false;
53+
export const warnAboutSpreadingKeyToJSX = false;
5354

5455
// Only used in www builds.
5556
export function addUserTimingListener() {

packages/shared/forks/ReactFeatureFlags.persistent.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export const disableUnstableCreatePortal = false;
5050
export const deferPassiveEffectCleanupDuringUnmount = false;
5151
export const runAllPassiveEffectDestroysBeforeCreates = false;
5252
export const isTestEnvironment = false;
53+
export const warnAboutSpreadingKeyToJSX = false;
5354

5455
// Only used in www builds.
5556
export function addUserTimingListener() {

packages/shared/forks/ReactFeatureFlags.test-renderer.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export const disableUnstableCreatePortal = false;
5050
export const deferPassiveEffectCleanupDuringUnmount = false;
5151
export const runAllPassiveEffectDestroysBeforeCreates = false;
5252
export const isTestEnvironment = true; // this should probably *never* change
53+
export const warnAboutSpreadingKeyToJSX = false;
5354

5455
// Only used in www builds.
5556
export function addUserTimingListener() {

packages/shared/forks/ReactFeatureFlags.test-renderer.www.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export const disableUnstableCreatePortal = false;
5050
export const deferPassiveEffectCleanupDuringUnmount = false;
5151
export const runAllPassiveEffectDestroysBeforeCreates = false;
5252
export const isTestEnvironment = true; // this should probably *never* change
53+
export const warnAboutSpreadingKeyToJSX = false;
5354

5455
// Only used in www builds.
5556
export function addUserTimingListener() {

packages/shared/forks/ReactFeatureFlags.testing.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export const disableUnstableCreatePortal = false;
5050
export const deferPassiveEffectCleanupDuringUnmount = false;
5151
export const runAllPassiveEffectDestroysBeforeCreates = false;
5252
export const isTestEnvironment = true;
53+
export const warnAboutSpreadingKeyToJSX = false;
5354

5455
// Only used in www builds.
5556
export function addUserTimingListener() {

packages/shared/forks/ReactFeatureFlags.testing.www.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export const disableUnstableCreatePortal = __EXPERIMENTAL__;
5050
export const deferPassiveEffectCleanupDuringUnmount = false;
5151
export const runAllPassiveEffectDestroysBeforeCreates = false;
5252
export const isTestEnvironment = true;
53+
export const warnAboutSpreadingKeyToJSX = false;
5354

5455
// Only used in www builds.
5556
export function addUserTimingListener() {

0 commit comments

Comments
 (0)