Attempt to simplify/fix warnAndMonitorForKeyUse
> The two callers of this function have different warning configs > internally (static_upstream/core/createWarning.js) so we can't sync it > like this without changing behavior. We should just split this out > into two separate warning calls probably – this code is a little > overabstracted. https://github.com/facebook/react/pull/4021#discussion_r31690020 @spicyj I think completely removing warnAndMonitorForKeyUse is a bit difficult, without duplicating a ton of code. This at least ensures that the format string passed to `warning` is unique. Plus, because the FB internal code in question only matches the beginning of the format string, I think there should be zero internal changes that need to be made to support this refactor.
Benjamin Woodruff committed
Jun 4, 2015 at 13:42 UTC
2fa1b2c810ac0462ee9cde5bc6b0c1af158f55e6
1 file changed
+44
-30
src/isomorphic/classic/element/ReactElementValidator.js
+44
-30
@@ -97,10 +97,18 @@ function validateExplicitKey(element, parentType) {
97
}
98
element._store.validated = true;
99
100
- warnAndMonitorForKeyUse(
101
- 'Each child in an array or iterator should have a unique "key" prop.',
102
- element,
103
- parentType
100
+ var addenda = getAddendaForKeyUse('uniqueKey', element, parentType);
101
+ if (addenda === null) {
102
+ // we already showed the warning
103
+ return;
104
+ }
105
+ warning(
106
+ false,
107
+ 'Each child in an array or iterator should have a unique "key" prop.' +
108
+ '%s%s%s',
109
+ addenda.parentOrOwner || '',
110
+ addenda.childOwner || '',
111
+ addenda.url || ''
112
);
113
}
114
@@ -117,10 +125,18 @@ function validatePropertyKey(name, element, parentType) {
125
if (!NUMERIC_PROPERTY_REGEX.test(name)) {
126
return;
127
}
120
- warnAndMonitorForKeyUse(
121
- 'Child objects should have non-numeric keys so ordering is preserved.',
122
- element,
123
- parentType
128
+ var addenda = getAddendaForKeyUse('numericKeys', element, parentType);
129
+ if (addenda === null) {
130
+ // we already showed the warning
131
+ return;
132
+ }
133
+ warning(
134
+ false,
135
+ 'Child objects should have non-numeric keys so ordering is preserved.' +
136
+ '%s%s%s',
137
+ addenda.parentOrOwner || '',
138
+ addenda.childOwner || '',
139
+ addenda.url || ''
140
);
141
}
142
@@ -128,49 +144,47 @@ function validatePropertyKey(name, element, parentType) {
144
* Shared warning and monitoring code for the key warnings.
145
*
146
* @internal
131
- * @param {string} message The base warning that gets output.
147
+ * @param {string} messageType A key used for de-duping warnings.
148
* @param {ReactElement} element Component that requires a key.
149
* @param {*} parentType element's parent's type.
150
+ * @returns {?object} A set of addenda to use in the warning message, or null
151
+ * if the warning has already been shown before (and shouldn't be shown again).
152
*/
135
-function warnAndMonitorForKeyUse(message, element, parentType) {
153
+function getAddendaForKeyUse(messageType, element, parentType) {
154
var ownerName = getCurrentOwnerDisplayName();
155
var parentName = typeof parentType === 'string' ?
156
parentType : parentType.displayName || parentType.name;
157
158
var useName = ownerName || parentName;
141
- var memoizer = ownerHasKeyUseWarning[message] || (
142
- ownerHasKeyUseWarning[message] = {}
159
+ var memoizer = ownerHasKeyUseWarning[messageType] || (
160
+ ownerHasKeyUseWarning[messageType] = {}
161
);
144
- if (memoizer.hasOwnProperty(useName)) {
145
- return;
162
+ if (memoizer[useName]) {
163
+ return null;
164
}
165
memoizer[useName] = true;
166
149
- var parentOrOwnerAddendum =
150
- ownerName ? ` Check the render method of ${ownerName}.` :
151
- parentName ? ` Check the React.render call using <${parentName}>.` :
152
- '';
167
+ var addenda = {
168
+ parentOrOwner:
169
+ ownerName ? ` Check the render method of ${ownerName}.` :
170
+ parentName ? ` Check the React.render call using <${parentName}>.` :
171
+ null,
172
+ url: ' See https://fb.me/react-warning-keys for more information.',
173
+ childOwner: null,
174
+ };
175
176
// Usually the current owner is the offender, but if it accepts children as a
177
// property, it may be the creator of the child that's responsible for
178
// assigning it a key.
157
- var childOwnerAddendum = '';
179
if (element &&
180
element._owner &&
181
element._owner !== ReactCurrentOwner.current) {
161
- // Name of the component that originally created this child.
162
- var childOwnerName = getName(element._owner);
163
-
164
- childOwnerAddendum = ` It was passed a child from ${childOwnerName}.`;
182
+ // Give the component that originally created this child.
183
+ addenda.childOwner =
184
+ ` It was passed a child from ${getName(element._owner)}.`;
185
}
186
167
- warning(
168
- false,
169
- '%s%s%s See https://fb.me/react-warning-keys for more information.',
170
- message,
171
- parentOrOwnerAddendum,
172
- childOwnerAddendum
173
- );
187
+ return addenda;
188
}
189
190
/**