Skip to content

Commit

Permalink
Fix Missing key Validation in React.Children (#29675)
Browse files Browse the repository at this point in the history
## Summary

In #29088, the validation logic
for `React.Children` inspected whether `mappedChild` — the return value
of the map callback — has a valid `key`. However, this deviates from
existing behavior which only warns if the original `child` is missing a
required `key`.

This fixes false positive `key` validation warnings when using
`React.Children`, by validating the original `child` instead of
`mappedChild`.

This is a more general fix that expands upon my previous fix in
#29662.

## How did you test this change?

```
$ yarn test ReactChildren-test.js
```

DiffTrain build for commit 8fd963a.
  • Loading branch information
yungsters committed May 31, 2024
1 parent 916c781 commit 6de1973
Show file tree
Hide file tree
Showing 13 changed files with 45 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<2a25705fbbe871438d92d9d2f32bfccc>>
* @generated SignedSource<<51857d1396b3dbf84785badc368366e6>>
*/

'use strict';
Expand Down Expand Up @@ -23471,7 +23471,7 @@ identifierPrefix, onUncaughtError, onCaughtError, onRecoverableError, transition
return root;
}

var ReactVersion = '19.0.0-rc-aa3d6c0840-20240530';
var ReactVersion = '19.0.0-rc-8fd963a1e5-20240530';

/*
* The `'' + value` pattern (used in perf-sensitive code) throws for Symbol
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<3d4979729ff28e957f06f4727c93a3a4>>
* @generated SignedSource<<62a7ec5b565b86a1ca4e89a8b6dfa33a>>
*/

"use strict";
Expand Down Expand Up @@ -9298,7 +9298,7 @@ var devToolsConfig$jscomp$inline_1047 = {
throw Error("TestRenderer does not support findFiberByHostInstance()");
},
bundleType: 0,
version: "19.0.0-rc-aa3d6c0840-20240530",
version: "19.0.0-rc-8fd963a1e5-20240530",
rendererPackageName: "react-test-renderer"
};
var internals$jscomp$inline_1234 = {
Expand Down Expand Up @@ -9329,7 +9329,7 @@ var internals$jscomp$inline_1234 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "19.0.0-rc-aa3d6c0840-20240530"
reconcilerVersion: "19.0.0-rc-8fd963a1e5-20240530"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1235 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<14d991ff27c63a57f423b8548b3f34ad>>
* @generated SignedSource<<4ac434762822d6280d83c5cda5c1341b>>
*/

"use strict";
Expand Down Expand Up @@ -9920,7 +9920,7 @@ var devToolsConfig$jscomp$inline_1130 = {
throw Error("TestRenderer does not support findFiberByHostInstance()");
},
bundleType: 0,
version: "19.0.0-rc-aa3d6c0840-20240530",
version: "19.0.0-rc-8fd963a1e5-20240530",
rendererPackageName: "react-test-renderer"
};
(function (internals) {
Expand Down Expand Up @@ -9964,7 +9964,7 @@ var devToolsConfig$jscomp$inline_1130 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "19.0.0-rc-aa3d6c0840-20240530"
reconcilerVersion: "19.0.0-rc-8fd963a1e5-20240530"
});
exports._Scheduler = Scheduler;
exports.act = act;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<f2d4c82ad9e691aab626fdc02f31be82>>
* @generated SignedSource<<d88d69aa4000a33e09ec957377ca26f8>>
*/

'use strict';
Expand All @@ -24,7 +24,7 @@ if (
}
var dynamicFlagsUntyped = require('ReactNativeInternalFeatureFlags');

var ReactVersion = '19.0.0-rc-aa3d6c0840-20240530';
var ReactVersion = '19.0.0-rc-8fd963a1e5-20240530';

// Re-export dynamic flags from the internal module.
var dynamicFlags = dynamicFlagsUntyped; // We destructure each value before re-exporting to avoid a dynamic look-up on
Expand Down Expand Up @@ -2011,11 +2011,16 @@ function mapIntoArray(children, array, escapedPrefix, nameSoFar, callback) {
) + '/' : '') + childKey);

{
if (nameSoFar !== '' && mappedChild.key == null) {
// We need to validate that this child should have had a key before assigning it one.
if (!newChild._store.validated) {
// We mark this child as having failed validation but we let the actual renderer
// print the warning later.
// If `child` was an element without a `key`, we need to validate if
// it should have had a `key`, before assigning one to `mappedChild`.
// $FlowFixMe[incompatible-type] Flow incorrectly thinks React.Portal doesn't have a key
if (nameSoFar !== '' && _child != null && isValidElement(_child) && _child.key == null) {
// We check truthiness of `child._store.validated` instead of being
// inequal to `1` to provide a bit of backward compatibility for any
// libraries (like `fbt`) which may be hacking this property.
if (_child._store && !_child._store.validated) {
// Mark this child as having failed validation, but let the actual
// renderer print the warning later.
newChild._store.validated = 2;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<e286590d896e861b94dedb356ce7ecea>>
* @generated SignedSource<<4cc9db1802bfed728048b5d62af26b8b>>
*/

"use strict";
Expand Down Expand Up @@ -604,4 +604,4 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactSharedInternals.H.useTransition();
};
exports.version = "19.0.0-rc-aa3d6c0840-20240530";
exports.version = "19.0.0-rc-8fd963a1e5-20240530";
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<86e1e6d22f22b9f5dcddbb5c1ecb70ca>>
* @generated SignedSource<<c411b87ad31eb8487965b83bc03b44eb>>
*/

"use strict";
Expand Down Expand Up @@ -608,7 +608,7 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactSharedInternals.H.useTransition();
};
exports.version = "19.0.0-rc-aa3d6c0840-20240530";
exports.version = "19.0.0-rc-8fd963a1e5-20240530";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
aa3d6c0840357eb469df9bd1c20b201197ce3bdc
8fd963a1e5ec89459cac27fb1d9ad193a0604110
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<7e84a017485205dca1fd369d6e72a750>>
* @generated SignedSource<<561a3a04b6eef3ab839c5c6c89289a8f>>
*/

'use strict';
Expand Down Expand Up @@ -26206,7 +26206,7 @@ identifierPrefix, onUncaughtError, onCaughtError, onRecoverableError, transition
return root;
}

var ReactVersion = '19.0.0-rc-aa3d6c0840-20240530';
var ReactVersion = '19.0.0-rc-8fd963a1e5-20240530';

/*
* The `'' + value` pattern (used in perf-sensitive code) throws for Symbol
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<29814ea154ff0145564ba37bc7c641e3>>
* @generated SignedSource<<43e2d3a64b19f02f63428367b171ef83>>
*/

"use strict";
Expand Down Expand Up @@ -10551,7 +10551,7 @@ var roots = new Map(),
devToolsConfig$jscomp$inline_1124 = {
findFiberByHostInstance: getInstanceFromNode,
bundleType: 0,
version: "19.0.0-rc-aa3d6c0840-20240530",
version: "19.0.0-rc-8fd963a1e5-20240530",
rendererPackageName: "react-native-renderer",
rendererConfig: {
getInspectorDataForInstance: getInspectorDataForInstance,
Expand Down Expand Up @@ -10594,7 +10594,7 @@ var internals$jscomp$inline_1350 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "19.0.0-rc-aa3d6c0840-20240530"
reconcilerVersion: "19.0.0-rc-8fd963a1e5-20240530"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1351 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<e19877e45f15454540281567e670bc5b>>
* @generated SignedSource<<01c2ef8f2c76da87ab46ae77a3777990>>
*/

"use strict";
Expand Down Expand Up @@ -11257,7 +11257,7 @@ var roots = new Map(),
devToolsConfig$jscomp$inline_1205 = {
findFiberByHostInstance: getInstanceFromNode,
bundleType: 0,
version: "19.0.0-rc-aa3d6c0840-20240530",
version: "19.0.0-rc-8fd963a1e5-20240530",
rendererPackageName: "react-native-renderer",
rendererConfig: {
getInspectorDataForInstance: getInspectorDataForInstance,
Expand Down Expand Up @@ -11313,7 +11313,7 @@ var roots = new Map(),
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "19.0.0-rc-aa3d6c0840-20240530"
reconcilerVersion: "19.0.0-rc-8fd963a1e5-20240530"
});
exports.createPortal = function (children, containerTag) {
return createPortal$1(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<aaf1d1cc950dfc6a86275919e7b1fc05>>
* @generated SignedSource<<df51ec7f297fbc971a9a0a5374b59a13>>
*/

'use strict';
Expand Down Expand Up @@ -26562,7 +26562,7 @@ identifierPrefix, onUncaughtError, onCaughtError, onRecoverableError, transition
return root;
}

var ReactVersion = '19.0.0-rc-aa3d6c0840-20240530';
var ReactVersion = '19.0.0-rc-8fd963a1e5-20240530';

/*
* The `'' + value` pattern (used in perf-sensitive code) throws for Symbol
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<5c72fdc520d6c302c378849c7a7fde5a>>
* @generated SignedSource<<4a450db295f67ea9874238584c4f431f>>
*/

"use strict";
Expand Down Expand Up @@ -10696,11 +10696,11 @@ function traverseOwnerTreeUp(hierarchy, instance) {
traverseOwnerTreeUp(hierarchy, instance);
}
var isomorphicReactPackageVersion = React.version;
if ("19.0.0-rc-aa3d6c0840-20240530" !== isomorphicReactPackageVersion)
if ("19.0.0-rc-8fd963a1e5-20240530" !== isomorphicReactPackageVersion)
throw Error(
'Incompatible React versions: The "react" and "react-native-renderer" packages must have the exact same version. Instead got:\n - react: ' +
(isomorphicReactPackageVersion +
"\n - react-native-renderer: 19.0.0-rc-aa3d6c0840-20240530\nLearn more: https://react.dev/warnings/version-mismatch")
"\n - react-native-renderer: 19.0.0-rc-8fd963a1e5-20240530\nLearn more: https://react.dev/warnings/version-mismatch")
);
if (
"function" !==
Expand Down Expand Up @@ -10750,7 +10750,7 @@ var roots = new Map(),
devToolsConfig$jscomp$inline_1192 = {
findFiberByHostInstance: getInstanceFromTag,
bundleType: 0,
version: "19.0.0-rc-aa3d6c0840-20240530",
version: "19.0.0-rc-8fd963a1e5-20240530",
rendererPackageName: "react-native-renderer",
rendererConfig: {
getInspectorDataForInstance: getInspectorDataForInstance,
Expand Down Expand Up @@ -10793,7 +10793,7 @@ var internals$jscomp$inline_1439 = {
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "19.0.0-rc-aa3d6c0840-20240530"
reconcilerVersion: "19.0.0-rc-8fd963a1e5-20240530"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1440 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @noflow
* @nolint
* @preventMunge
* @generated SignedSource<<b6669ae6e190e7f12b84b5b57ba715e7>>
* @generated SignedSource<<0667378dfc8028ec5ee4bb3c1517736f>>
*/

"use strict";
Expand Down Expand Up @@ -11403,11 +11403,11 @@ function traverseOwnerTreeUp(hierarchy, instance) {
traverseOwnerTreeUp(hierarchy, instance);
}
var isomorphicReactPackageVersion = React.version;
if ("19.0.0-rc-aa3d6c0840-20240530" !== isomorphicReactPackageVersion)
if ("19.0.0-rc-8fd963a1e5-20240530" !== isomorphicReactPackageVersion)
throw Error(
'Incompatible React versions: The "react" and "react-native-renderer" packages must have the exact same version. Instead got:\n - react: ' +
(isomorphicReactPackageVersion +
"\n - react-native-renderer: 19.0.0-rc-aa3d6c0840-20240530\nLearn more: https://react.dev/warnings/version-mismatch")
"\n - react-native-renderer: 19.0.0-rc-8fd963a1e5-20240530\nLearn more: https://react.dev/warnings/version-mismatch")
);
if (
"function" !==
Expand Down Expand Up @@ -11457,7 +11457,7 @@ var roots = new Map(),
devToolsConfig$jscomp$inline_1273 = {
findFiberByHostInstance: getInstanceFromTag,
bundleType: 0,
version: "19.0.0-rc-aa3d6c0840-20240530",
version: "19.0.0-rc-8fd963a1e5-20240530",
rendererPackageName: "react-native-renderer",
rendererConfig: {
getInspectorDataForInstance: getInspectorDataForInstance,
Expand Down Expand Up @@ -11513,7 +11513,7 @@ var roots = new Map(),
scheduleRoot: null,
setRefreshHandler: null,
getCurrentFiber: null,
reconcilerVersion: "19.0.0-rc-aa3d6c0840-20240530"
reconcilerVersion: "19.0.0-rc-8fd963a1e5-20240530"
});
exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = {
computeComponentStackForErrorReporting: function (reactTag) {
Expand Down

0 comments on commit 6de1973

Please sign in to comment.