@samitouri / QOS-React-2 / commits / 207b03c56d

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 }