diff --git a/packages/react/src/__tests__/ReactChildren-test.js b/packages/react/src/__tests__/ReactChildren-test.js index 08560a4f1ec14..6a97465d3d97f 100644 --- a/packages/react/src/__tests__/ReactChildren-test.js +++ b/packages/react/src/__tests__/ReactChildren-test.js @@ -868,6 +868,45 @@ describe('ReactChildren', () => { ]); }); + it('should warn for flattened children lists', async () => { + function ComponentRenderingFlattenedChildren({children}) { + return
{React.Children.toArray(children)}
; + } + + const container = document.createElement('div'); + const root = ReactDOMClient.createRoot(container); + await expect(async () => { + await act(() => { + root.render( + + {[
]} + , + ); + }); + }).toErrorDev([ + 'Warning: Each child in a list should have a unique "key" prop.', + ]); + }); + + it('does not warn for flattened positional children', async () => { + function ComponentRenderingFlattenedChildren({children}) { + return
{React.Children.toArray(children)}
; + } + + const container = document.createElement('div'); + const root = ReactDOMClient.createRoot(container); + await expect(async () => { + await act(() => { + root.render( + +
+
+ , + ); + }); + }).toErrorDev([]); + }); + it('should escape keys', () => { const zero =
; const one =
; diff --git a/packages/react/src/jsx/ReactJSXElement.js b/packages/react/src/jsx/ReactJSXElement.js index a5a9880b05b9a..0f8b9f397df5b 100644 --- a/packages/react/src/jsx/ReactJSXElement.js +++ b/packages/react/src/jsx/ReactJSXElement.js @@ -953,7 +953,7 @@ export function createElement(type, config, children) { } export function cloneAndReplaceKey(oldElement, newKey) { - return ReactElement( + const clonedElement = ReactElement( oldElement.type, newKey, // When enableRefAsProp is on, this argument is ignored. This check only @@ -966,6 +966,11 @@ export function cloneAndReplaceKey(oldElement, newKey) { __DEV__ && enableOwnerStacks ? oldElement._debugStack : undefined, __DEV__ && enableOwnerStacks ? oldElement._debugTask : undefined, ); + if (__DEV__) { + // The cloned element should inherit the original element's key validation. + clonedElement._store.validated = oldElement._store.validated; + } + return clonedElement; } /**