Dedupe owner-is-important warning.
Jim committed
Feb 13, 2015 at 17:17 UTC
207b03c56d8630a4baa62bacb633d6fcc1f4b2e9
3 files changed
+72
-13
src/core/__tests__/ReactCompositeComponent-test.js
+44
@@ -501,6 +501,50 @@ describe('ReactCompositeComponent', function() {
501
);
502
});
503
504
+ it('should warn when owner is necessary', function() {
505
+
506
+ var Chooser = React.createClass({
507
+ render: function() {
508
+ return this.props.selection == 1 ? this.props.child1 : this.props.child2;
509
+ }
510
+ });
511
+
512
+ var CoolParent1 = React.createClass({
513
+ render: function() {
514
+ return <Chooser
515
+ selection={this.props.selection}
516
+ child1={<input value='foo' readOnly='true' />}
517
+ child2={this.props.child2} />;
518
+ }
519
+ });
520
+
521
+ var CoolParent2 = React.createClass({
522
+ render: function() {
523
+ return <CoolParent1
524
+ selection={this.props.selection}
525
+ child2={<input value='foo' readOnly='true' />} />;
526
+ }
527
+ });
528
+
529
+ var div = document.createElement('div');
530
+ React.render(<CoolParent2 selection={1} />, div);
531
+ expect(console.warn.argsForCall.length).toBe(0);
532
+ React.render(<CoolParent2 selection={2} />, div);
533
+ expect(console.warn.argsForCall.length).toBe(1);
534
+ React.render(<CoolParent2 selection={1} />, div);
535
+ React.render(<CoolParent2 selection={2} />, div);
536
+ expect(console.warn.argsForCall.length).toBe(1);
537
+
538
+ expect(console.warn.argsForCall[0][0]).toBe(
539
+ 'Warning: <input /> is being rendered by both CoolParent1 and ' +
540
+ 'CoolParent2 using the same key (null) in the same place. Currently, ' +
541
+ 'this means that they don\'t preserve state. This behavior should be ' +
542
+ 'very rare so we\'re considering deprecating it. Please contact the ' +
543
+ 'React team and explain your use case so that we can take that into ' +
544
+ 'consideration.'
545
+ );
546
+ });
547
+
548
it('should pass context', function() {
549
var childInstance = null;
550
var grandchildInstance = null;
src/core/instantiateReactComponent.js
+4
@@ -114,6 +114,10 @@ function instantiateReactComponent(node, parentCompositeType) {
114
instance._mountIndex = 0;
115
instance._mountImage = null;
116
117
+ if (__DEV__) {
118
+ instance._isOwnerNecessary = false;
119
+ }
120
+
121
// Internal instances should fully constructed at this point, so they should
122
// not get any new fields added to them at this point.
123
if (__DEV__) {
src/core/shouldUpdateReactComponent.js
+24
-13
@@ -63,19 +63,30 @@ function shouldUpdateReactComponent(prevElement, nextElement) {
63
if (typeof nextElement.type !== 'string' ||
64
nextElement.type === 'input' ||
65
nextElement.type === 'textarea') {
66
- warning(
67
- false,
68
- '<%s /> is being rendered by both %s and %s using the same key ' +
69
- '(%s) in the same place. Currently, this means that they ' +
70
- 'don\'t preserve state. This behavior should be very rare ' +
71
- 'so we\'re considering deprecating it. Please contact the ' +
72
- 'React team and explain your use case so that we can take that ' +
73
- 'into consideration.',
74
- nextDisplayName || 'Unknown Component',
75
- prevName || '[Unknown]',
76
- nextName || '[Unknown]',
77
- prevElement.key
78
- );
66
+ if ((prevElement._owner != null &&
67
+ prevElement._owner._isOwnerNecessary === false) ||
68
+ (nextElement._owner != null &&
69
+ nextElement._owner._isOwnerNecessary === false)) {
70
+ if (prevElement._owner != null) {
71
+ prevElement._owner._isOwnerNecessary = true;
72
+ }
73
+ if (nextElement._owner != null) {
74
+ nextElement._owner._isOwnerNecessary = true;
75
+ }
76
+ warning(
77
+ false,
78
+ '<%s /> is being rendered by both %s and %s using the same ' +
79
+ 'key (%s) in the same place. Currently, this means that ' +
80
+ 'they don\'t preserve state. This behavior should be very ' +
81
+ 'rare so we\'re considering deprecating it. Please contact ' +
82
+ 'the React team and explain your use case so that we can ' +
83
+ 'take that into consideration.',
84
+ nextDisplayName || 'Unknown Component',
85
+ prevName || '[Unknown]',
86
+ nextName || '[Unknown]',
87
+ prevElement.key
88
+ );
89
+ }
90
}
91
}
92
}