@samitouri / QOS-React-2 / commits / 2fa1b2c810

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 /**