@@ -48,11 +48,25 @@ var ownerHasKeyUseWarning = {};
4848
4949var loggedTypeFailures = { } ;
5050
51+ function getCurrentComponentErrorInfo ( parentType ) {
52+ var info = getDeclarationErrorAddendum ( ) ;
53+
54+ if ( ! info ) {
55+ var parentName = typeof parentType === 'string' ?
56+ parentType : parentType . displayName || parentType . name ;
57+ if ( parentName ) {
58+ info = ` Check the top-level render call using <${ parentName } >.` ;
59+ }
60+ }
61+ return info ;
62+ }
63+
5164/**
5265 * Warn if the element doesn't have an explicit key assigned to it.
5366 * This element is in an array. The array could grow and shrink or be
5467 * reordered. All children that haven't already been validated are required to
55- * have a "key" property assigned to it.
68+ * have a "key" property assigned to it. Error statuses are cached so a warning
69+ * will only be shown once.
5670 *
5771 * @internal
5872 * @param {ReactElement } element Element that requires a key.
@@ -64,67 +78,36 @@ function validateExplicitKey(element, parentType) {
6478 }
6579 element . _store . validated = true ;
6680
67- var addenda = getAddendaForKeyUse ( 'uniqueKey' , element , parentType ) ;
68- if ( addenda === null ) {
69- // we already showed the warning
70- return ;
71- }
72- warning (
73- false ,
74- 'Each child in an array or iterator should have a unique "key" prop.' +
75- '%s%s%s' ,
76- addenda . parentOrOwner || '' ,
77- addenda . childOwner || '' ,
78- addenda . url || ''
81+ var memoizer = ownerHasKeyUseWarning . uniqueKey || (
82+ ownerHasKeyUseWarning . uniqueKey = { }
7983 ) ;
80- }
81-
82- /**
83- * Shared warning and monitoring code for the key warnings.
84- *
85- * @internal
86- * @param {string } messageType A key used for de-duping warnings.
87- * @param {ReactElement } element Component that requires a key.
88- * @param {* } parentType element's parent's type.
89- * @returns {?object } A set of addenda to use in the warning message, or null
90- * if the warning has already been shown before (and shouldn't be shown again).
91- */
92- function getAddendaForKeyUse ( messageType , element , parentType ) {
93- var addendum = getDeclarationErrorAddendum ( ) ;
94- if ( ! addendum ) {
95- var parentName = typeof parentType === 'string' ?
96- parentType : parentType . displayName || parentType . name ;
97- if ( parentName ) {
98- addendum = ` Check the top-level render call using <${ parentName } >.` ;
99- }
100- }
10184
102- var memoizer = ownerHasKeyUseWarning [ messageType ] || (
103- ownerHasKeyUseWarning [ messageType ] = { }
104- ) ;
105- if ( memoizer [ addendum ] ) {
106- return null ;
85+ var currentComponentErrorInfo = getCurrentComponentErrorInfo ( parentType ) ;
86+ if ( memoizer [ currentComponentErrorInfo ] ) {
87+ return ;
10788 }
108- memoizer [ addendum ] = true ;
109-
110- var addenda = {
111- parentOrOwner : addendum ,
112- url : ' See https://fb.me/react-warning-keys for more information.' ,
113- childOwner : null ,
114- } ;
89+ memoizer [ currentComponentErrorInfo ] = true ;
11590
11691 // Usually the current owner is the offender, but if it accepts children as a
11792 // property, it may be the creator of the child that's responsible for
11893 // assigning it a key.
94+ var childOwner = '' ;
11995 if ( element &&
12096 element . _owner &&
12197 element . _owner !== ReactCurrentOwner . current ) {
12298 // Give the component that originally created this child.
123- addenda . childOwner =
99+ childOwner =
124100 ` It was passed a child from ${ element . _owner . getName ( ) } .` ;
125101 }
126102
127- return addenda ;
103+ warning (
104+ false ,
105+ 'Each child in an array or iterator should have a unique "key" prop.' +
106+ '%s%s See https://fb.me/react-warning-keys for more information.%s' ,
107+ currentComponentErrorInfo ,
108+ childOwner ,
109+ ReactComponentTreeDevtool . getCurrentStackAddendum ( element )
110+ ) ;
128111}
129112
130113/**
0 commit comments