From 3b43f3190bbcc5d4cfe77dbc665e03b7b95d35b2 Mon Sep 17 00:00:00 2001 From: Flarnie Marchan Date: Wed, 12 Jul 2017 15:49:41 -0700 Subject: [PATCH] Reword duplicate key warning (#10148) * Reword duplicate key warning **what is the change?:** - Removes the now-inaccurate description of behavior around duplicate keys - Adds link to 'key' docs page - Changes tone to be more casual and friendly Alternative wording idea; 'Encountered two children with the same key, ${key} Child keys must be unique; using duplicate keys is not supported and will cause unexpected behavior in some versions of React. See https://fb.me/react-warning-keys for more information on how to fix this.' **why make this change?:** Mainly this change was needed because in React 16, duplicate keys will not cause omission of items with duplicate keys. All items will be rendered. It could happen that in future versions of React we will have different behavior though. **test plan:** `yarn test` **issue:** Wishlist item on https://github.com/facebook/react/issues/8854 * Further improve wording of duplicate key error **what is the change?:** Another tweak to the wording of this error to make it more clear and accurate. **why make this change?:** The previous tweak was too casual in tone and still not clear enough. **test plan:** `yarn test` and `REACT_DOM_JEST_USE_FIBER=1 yarn run test` **issue:** Wishlist item on https://github.com/facebook/react/issues/8854 * Run prettier * Fix typo in error message for duplicate keys **what is the change?:** Fixed a typo in the updated message * Fix two more typo spots --- src/isomorphic/children/flattenChildren.js | 6 +++-- .../__tests__/ReactChildReconciler-test.js | 26 +++++++++++++------ .../__tests__/ReactMultiChild-test.js | 16 +++++++----- src/renderers/shared/fiber/ReactChildFiber.js | 8 +++--- .../stack/reconciler/ReactChildReconciler.js | 9 ++++--- .../stack/reconciler/flattenStackChildren.js | 7 +++-- 6 files changed, 48 insertions(+), 24 deletions(-) diff --git a/src/isomorphic/children/flattenChildren.js b/src/isomorphic/children/flattenChildren.js index fa8ea58d74606..bbed350087bab 100644 --- a/src/isomorphic/children/flattenChildren.js +++ b/src/isomorphic/children/flattenChildren.js @@ -38,8 +38,10 @@ function flattenSingleChildIntoContext( warning( false, 'flattenChildren(...): Encountered two children with the same key, ' + - '`%s`. Child keys must be unique; when two children share a key, only ' + - 'the first child will be used.%s', + '`%s`. Keys should be unique so that components maintain their ' + + 'identity across updates. Non-unique keys may cause children to ' + + 'be duplicated and/or omitted — the behavior is ' + + 'unsupported and could change in a future version.%s', unescapeInDev(name), ReactComponentTreeHook.getStackAddendumByID(selfDebugID), ); diff --git a/src/renderers/__tests__/ReactChildReconciler-test.js b/src/renderers/__tests__/ReactChildReconciler-test.js index 4ad42d83457ce..13826f03989da 100644 --- a/src/renderers/__tests__/ReactChildReconciler-test.js +++ b/src/renderers/__tests__/ReactChildReconciler-test.js @@ -60,7 +60,10 @@ describe('ReactChildReconciler', () => { expectDev(console.error.calls.count()).toBe(1); expectDev(console.error.calls.argsFor(0)[0]).toContain( - 'Child keys must be unique; when two children share a key, only the first child will be used.', + 'Keys should be unique so that components maintain their identity ' + + 'across updates. Non-unique keys may cause children to be ' + + 'duplicated and/or omitted — the behavior is unsupported and ' + + 'could change in a future version.', ); }); @@ -92,9 +95,11 @@ describe('ReactChildReconciler', () => { normalizeCodeLocInfo(console.error.calls.argsFor(0)[0]), ).toContain( 'Encountered two children with the same key, `1`. ' + - 'Child keys must be unique; when two children share a key, ' + - 'only the first child will be used.\n' + - ' in div (at **)\n' + + 'Keys should be unique so that components maintain their identity ' + + 'across updates. Non-unique keys may cause children to be ' + + 'duplicated and/or omitted — the behavior is unsupported and ' + + 'could change in a future version.', + ' in div (at **)\n' + ' in Component (at **)\n' + ' in Parent (at **)\n' + ' in GrandParent (at **)', @@ -114,7 +119,10 @@ describe('ReactChildReconciler', () => { expectDev(console.error.calls.count()).toBe(1); expectDev(console.error.calls.argsFor(0)[0]).toContain( - 'Child keys must be unique; when two children share a key, only the first child will be used.', + 'Keys should be unique so that components maintain their identity ' + + 'across updates. Non-unique keys may cause children to be ' + + 'duplicated and/or omitted — the behavior is unsupported and ' + + 'could change in a future version.', ); }); @@ -146,9 +154,11 @@ describe('ReactChildReconciler', () => { normalizeCodeLocInfo(console.error.calls.argsFor(0)[0]), ).toContain( 'Encountered two children with the same key, `1`. ' + - 'Child keys must be unique; when two children share a key, ' + - 'only the first child will be used.\n' + - ' in div (at **)\n' + + 'Keys should be unique so that components maintain their identity ' + + 'across updates. Non-unique keys may cause children to be ' + + 'duplicated and/or omitted — the behavior is unsupported and ' + + 'could change in a future version.', + ' in div (at **)\n' + ' in Component (at **)\n' + ' in Parent (at **)\n' + ' in GrandParent (at **)', diff --git a/src/renderers/__tests__/ReactMultiChild-test.js b/src/renderers/__tests__/ReactMultiChild-test.js index f8262f8b8a167..cdf104ba3b3a0 100644 --- a/src/renderers/__tests__/ReactMultiChild-test.js +++ b/src/renderers/__tests__/ReactMultiChild-test.js @@ -189,9 +189,11 @@ describe('ReactMultiChild', () => { normalizeCodeLocInfo(console.error.calls.argsFor(0)[0]), ).toContain( 'Encountered two children with the same key, `1`. ' + - 'Child keys must be unique; when two children share a key, ' + - 'only the first child will be used.\n' + - ' in div (at **)\n' + + 'Keys should be unique so that components maintain their identity ' + + 'across updates. Non-unique keys may cause children to be ' + + 'duplicated and/or omitted — the behavior is unsupported and ' + + 'could change in a future version.', + ' in div (at **)\n' + ' in WrapperComponent (at **)\n' + ' in div (at **)\n' + ' in Parent (at **)', @@ -254,9 +256,11 @@ describe('ReactMultiChild', () => { normalizeCodeLocInfo(console.error.calls.argsFor(0)[0]), ).toContain( 'Encountered two children with the same key, `1`. ' + - 'Child keys must be unique; when two children share a key, ' + - 'only the first child will be used.\n' + - ' in div (at **)\n' + + 'Keys should be unique so that components maintain their identity ' + + 'across updates. Non-unique keys may cause children to be ' + + 'duplicated and/or omitted — the behavior is unsupported and ' + + 'could change in a future version.', + ' in div (at **)\n' + ' in WrapperComponent (at **)\n' + ' in div (at **)\n' + ' in Parent (at **)', diff --git a/src/renderers/shared/fiber/ReactChildFiber.js b/src/renderers/shared/fiber/ReactChildFiber.js index d918261264c9e..f5f46616197a2 100644 --- a/src/renderers/shared/fiber/ReactChildFiber.js +++ b/src/renderers/shared/fiber/ReactChildFiber.js @@ -718,9 +718,11 @@ function ChildReconciler(shouldClone, shouldTrackSideEffects) { } warning( false, - 'Encountered two children with the same key, ' + - '`%s`. Child keys must be unique; when two children share a key, ' + - 'only the first child will be used.%s', + 'Encountered two children with the same key, `%s`. ' + + 'Keys should be unique so that components maintain their identity ' + + 'across updates. Non-unique keys may cause children to be ' + + 'duplicated and/or omitted — the behavior is unsupported and ' + + 'could change in a future version.%s', key, getCurrentFiberStackAddendum(), ); diff --git a/src/renderers/shared/stack/reconciler/ReactChildReconciler.js b/src/renderers/shared/stack/reconciler/ReactChildReconciler.js index c43f8cd201478..b15503d5788ad 100644 --- a/src/renderers/shared/stack/reconciler/ReactChildReconciler.js +++ b/src/renderers/shared/stack/reconciler/ReactChildReconciler.js @@ -46,9 +46,12 @@ function instantiateChild(childInstances, child, name, selfDebugID) { if (!keyUnique) { warning( false, - 'flattenChildren(...): Encountered two children with the same key, ' + - '`%s`. Child keys must be unique; when two children share a key, only ' + - 'the first child will be used.%s', + 'flattenChildren(...):' + + 'Encountered two children with the same key, `%s`. ' + + 'Keys should be unique so that components maintain their identity ' + + 'across updates. Non-unique keys may cause children to be ' + + 'duplicated and/or omitted — the behavior is unsupported and ' + + 'could change in a future version.%s', KeyEscapeUtils.unescapeInDev(name), ReactComponentTreeHook.getStackAddendumByID(selfDebugID), ); diff --git a/src/renderers/shared/stack/reconciler/flattenStackChildren.js b/src/renderers/shared/stack/reconciler/flattenStackChildren.js index da0f50df913cd..295bc25e3903d 100644 --- a/src/renderers/shared/stack/reconciler/flattenStackChildren.js +++ b/src/renderers/shared/stack/reconciler/flattenStackChildren.js @@ -57,8 +57,11 @@ function flattenSingleChildIntoContext( warning( false, 'flattenChildren(...): Encountered two children with the same key, ' + - '`%s`. Child keys must be unique; when two children share a key, only ' + - 'the first child will be used.%s', + '`%s`. ' + + 'Keys should be unique so that components maintain their identity ' + + 'across updates. Non-unique keys may cause children to be ' + + 'duplicated and/or omitted — the behavior is unsupported and ' + + 'could change in a future version.%s', KeyEscapeUtils.unescapeInDev(name), ReactComponentTreeHook.getStackAddendumByID(selfDebugID), );