Ignore specifically React warning getter in ReactElement
We don’t want to have different behavior in development and production. Previously, we used to ignore getters on key/ref in dev, but we’d read them in prod. Now, we only ignore the getters that we *know* we created so the production logic doesn’t differ.
Dan Abramov committed
May 26, 2016 at 01:01 UTC
a432afa750f0b59412c79c0ca9db4df42a0f8491
3 files changed
+55
-83
src/isomorphic/classic/element/ReactElement.js
+45
-36
@@ -34,9 +34,11 @@ var specialPropKeyWarningShown, specialPropRefWarningShown;
34
35
function hasValidRef(config) {
36
if (__DEV__) {
37
- if (hasOwnProperty.call(config, 'ref') &&
38
- Object.getOwnPropertyDescriptor(config, 'ref').get) {
39
- return false;
37
+ if (hasOwnProperty.call(config, 'ref')) {
38
+ var getter = Object.getOwnPropertyDescriptor(config, 'ref').get;
39
+ if (getter && getter.isReactWarning) {
40
+ return false;
41
+ }
42
}
43
}
44
return config.ref !== undefined;
@@ -44,9 +46,11 @@ function hasValidRef(config) {
46
47
function hasValidKey(config) {
48
if (__DEV__) {
47
- if (hasOwnProperty.call(config, 'key') &&
48
- Object.getOwnPropertyDescriptor(config, 'key').get) {
49
- return false;
49
+ if (hasOwnProperty.call(config, 'key')) {
50
+ var getter = Object.getOwnPropertyDescriptor(config, 'key').get;
51
+ if (getter && getter.isReactWarning) {
52
+ return false;
53
+ }
54
}
55
}
56
return config.key !== undefined;
@@ -201,45 +205,50 @@ ReactElement.createElement = function(type, config, children) {
205
}
206
}
207
if (__DEV__) {
204
- // Create dummy `key` and `ref` property to `props` to warn users
205
- // against its use
208
+ // Create dummy `key` and `ref` property to `props` to warn users against its use
209
+ function warnAboutAccessingKey() {
210
+ if (!specialPropKeyWarningShown) {
211
+ specialPropKeyWarningShown = true;
212
+ warning(
213
+ false,
214
+ '%s: `key` is not a prop. Trying to access it will result ' +
215
+ 'in `undefined` being returned. If you need to access the same ' +
216
+ 'value within the child component, you should pass it as a different ' +
217
+ 'prop. (https://fb.me/react-special-props)',
218
+ typeof type === 'function' && 'displayName' in type ? type.displayName : 'Element'
219
+ );
220
+ }
221
+ return undefined;
222
+ }
223
+ warnAboutAccessingKey.isReactWarning = true;
224
+
225
+ function warnAboutAccessingRef() {
226
+ if (!specialPropRefWarningShown) {
227
+ specialPropRefWarningShown = true;
228
+ warning(
229
+ false,
230
+ '%s: `ref` is not a prop. Trying to access it will result ' +
231
+ 'in `undefined` being returned. If you need to access the same ' +
232
+ 'value within the child component, you should pass it as a different ' +
233
+ 'prop. (https://fb.me/react-special-props)',
234
+ typeof type === 'function' && 'displayName' in type ? type.displayName : 'Element'
235
+ );
236
+ }
237
+ return undefined;
238
+ }
239
+ warnAboutAccessingRef.isReactWarning = true;
240
+
241
if (typeof props.$$typeof === 'undefined' ||
242
props.$$typeof !== REACT_ELEMENT_TYPE) {
243
if (!props.hasOwnProperty('key')) {
244
Object.defineProperty(props, 'key', {
210
- get: function() {
211
- if (!specialPropKeyWarningShown) {
212
- specialPropKeyWarningShown = true;
213
- warning(
214
- false,
215
- '%s: `key` is not a prop. Trying to access it will result ' +
216
- 'in `undefined` being returned. If you need to access the same ' +
217
- 'value within the child component, you should pass it as a different ' +
218
- 'prop. (https://fb.me/react-special-props)',
219
- typeof type === 'function' && 'displayName' in type ? type.displayName : 'Element'
220
- );
221
- }
222
- return undefined;
223
- },
245
+ get: warnAboutAccessingKey,
246
configurable: true,
247
});
248
}
249
if (!props.hasOwnProperty('ref')) {
250
Object.defineProperty(props, 'ref', {
229
- get: function() {
230
- if (!specialPropRefWarningShown) {
231
- specialPropRefWarningShown = true;
232
- warning(
233
- false,
234
- '%s: `ref` is not a prop. Trying to access it will result ' +
235
- 'in `undefined` being returned. If you need to access the same ' +
236
- 'value within the child component, you should pass it as a different ' +
237
- 'prop. (https://fb.me/react-special-props)',
238
- typeof type === 'function' && 'displayName' in type ? type.displayName : 'Element'
239
- );
240
- }
241
- return undefined;
242
- },
251
+ get: warnAboutAccessingRef,
252
configurable: true,
253
});
254
}
src/isomorphic/classic/element/__tests__/ReactElement-test.js
+5
-21
@@ -199,27 +199,11 @@ describe('ReactElement', function() {
199
expect(element.props).toEqual(expectation);
200
});
201
202
- it('ignores key and ref getters', function() {
203
- var props = {
204
- foo: '56',
205
- };
206
- Object.defineProperty(props, 'key', {
207
- get: function() {
208
- return '12';
209
- },
210
- });
211
- Object.defineProperty(props, 'ref', {
212
- get: function() {
213
- return '34';
214
- },
215
- });
216
- var element = React.createFactory(ComponentClass)(props);
217
- expect(element.type).toBe(ComponentClass);
218
- expect(element.key).toBe(null);
219
- expect(element.ref).toBe(null);
220
- var expectation = {foo: '56'};
221
- Object.freeze(expectation);
222
- expect(element.props).toEqual(expectation);
202
+ it('ignores key and ref warning getters', function() {
203
+ var elementA = React.createElement('div');
204
+ var elementB = React.createElement('div', elementA.props);
205
+ expect(elementB.key).toBe(null);
206
+ expect(elementB.ref).toBe(null);
207
});
208
209
it('coerces the key to a string', function() {
src/isomorphic/classic/element/__tests__/ReactElementClone-test.js
+5
-26
@@ -322,32 +322,11 @@ describe('ReactElementClone', function() {
322
);
323
});
324
325
- it('should ignore key and ref getters', function() {
326
- var element = React.createFactory(ComponentClass)({
327
- key: '12',
328
- ref: '34',
329
- foo: '56',
330
- });
331
- var props = {
332
- foo: 'ef',
333
- };
334
- Object.defineProperty(props, 'key', {
335
- get: function() {
336
- return 'ab';
337
- },
338
- });
339
- Object.defineProperty(props, 'ref', {
340
- get: function() {
341
- return 'cd';
342
- },
343
- });
344
- var clone = React.cloneElement(element, props);
345
- expect(clone.type).toBe(ComponentClass);
346
- expect(clone.key).toBe('12');
347
- expect(clone.ref).toBe('34');
348
- var expectation = {foo: 'ef'};
349
- Object.freeze(expectation);
350
- expect(clone.props).toEqual(expectation);
325
+ it('should ignore key and ref warning getters', function() {
326
+ var elementA = React.createElement('div');
327
+ var elementB = React.cloneElement(elementA, elementA.props);
328
+ expect(elementB.key).toBe(null);
329
+ expect(elementB.ref).toBe(null);
330
});
331
332
it('should ignore undefined key and ref', function() {