Revert "Removed setProps and replaceProps (both previously deprecated)"
This reverts commit 721fe7354142c866db2ebcc727a2472a3f3e0cc6. We'll keep these with a warning for one more release.
Ben Alpert committed
Jul 3, 2015 at 10:09 UTC
4eb889b72ee13402d1a0b10e9458c95d7445f7e1
16 files changed
+386
-45
src/isomorphic/classic/__tests__/ReactContextValidator-test.js
+3
-3
@@ -121,9 +121,9 @@ describe('ReactContextValidator', function() {
121
},
122
});
123
124
- var container = document.createElement('div');
125
- React.render(<Parent foo="abc" />, container);
126
- React.render(<Parent foo="def" />, container);
124
+ var instance = <Parent foo="abc" />;
125
+ instance = ReactTestUtils.renderIntoDocument(instance);
126
+ instance.replaceProps({foo: 'def'});
127
expect(actualComponentWillReceiveProps).toEqual({foo: 'def'});
128
expect(actualShouldComponentUpdate).toEqual({foo: 'def'});
129
expect(actualComponentWillUpdate).toEqual({foo: 'def'});
src/isomorphic/classic/class/ReactClass.js
+32
@@ -728,6 +728,38 @@ var ReactClassMixin = {
728
isMounted: function() {
729
return this.updater.isMounted(this);
730
},
731
+
732
+ /**
733
+ * Sets a subset of the props.
734
+ *
735
+ * @param {object} partialProps Subset of the next props.
736
+ * @param {?function} callback Called after props are updated.
737
+ * @final
738
+ * @public
739
+ * @deprecated
740
+ */
741
+ setProps: function(partialProps, callback) {
742
+ this.updater.enqueueSetProps(this, partialProps);
743
+ if (callback) {
744
+ this.updater.enqueueCallback(this, callback);
745
+ }
746
+ },
747
+
748
+ /**
749
+ * Replace all the props.
750
+ *
751
+ * @param {object} newProps Subset of the next props.
752
+ * @param {?function} callback Called after props are updated.
753
+ * @final
754
+ * @public
755
+ * @deprecated
756
+ */
757
+ replaceProps: function(newProps, callback) {
758
+ this.updater.enqueueReplaceProps(this, newProps);
759
+ if (callback) {
760
+ this.updater.enqueueCallback(this, callback);
761
+ }
762
+ },
763
};
764
765
var ReactClassComponent = function() {};
src/isomorphic/modern/class/ReactComponent.js
+8
@@ -112,11 +112,19 @@ if (__DEV__) {
112
'Instead, make sure to clean up subscriptions and pending requests in ' +
113
'componentWillUnmount to prevent memory leaks.',
114
],
115
+ replaceProps: [
116
+ 'replaceProps',
117
+ 'Instead, call React.render again at the top level.',
118
+ ],
119
replaceState: [
120
'replaceState',
121
'Refactor your code to use setState instead (see ' +
122
'https://github.com/facebook/react/issues/3236).',
123
],
124
+ setProps: [
125
+ 'setProps',
126
+ 'Instead, call React.render again at the top level.',
127
+ ],
128
};
129
var defineDeprecationWarning = function(methodName, info) {
130
try {
src/isomorphic/modern/class/ReactNoopUpdateQueue.js
+23
@@ -98,6 +98,29 @@ var ReactNoopUpdateQueue = {
98
enqueueSetState: function(publicInstance, partialState) {
99
warnTDZ(publicInstance, 'setState');
100
},
101
+
102
+ /**
103
+ * Sets a subset of the props.
104
+ *
105
+ * @param {ReactClass} publicInstance The instance that should rerender.
106
+ * @param {object} partialProps Subset of the next props.
107
+ * @internal
108
+ */
109
+ enqueueSetProps: function(publicInstance, partialProps) {
110
+ warnTDZ(publicInstance, 'setProps');
111
+ },
112
+
113
+ /**
114
+ * Replaces all of the props.
115
+ *
116
+ * @param {ReactClass} publicInstance The instance that should rerender.
117
+ * @param {object} props New props.
118
+ * @internal
119
+ */
120
+ enqueueReplaceProps: function(publicInstance, props) {
121
+ warnTDZ(publicInstance, 'replaceProps');
122
+ },
123
+
124
};
125
126
module.exports = ReactNoopUpdateQueue;
src/isomorphic/modern/class/__tests__/ReactCoffeeScriptClass-test.coffee
+9
-1
@@ -346,7 +346,9 @@ describe 'ReactCoffeeScriptClass', ->
346
expect(-> instance.getDOMNode()).toThrow()
347
expect(-> instance.replaceState {}).toThrow()
348
expect(-> instance.isMounted()).toThrow()
349
- expect(console.error.calls.length).toBe 3
349
+ expect(-> instance.setProps name: 'bar').toThrow()
350
+ expect(-> instance.replaceProps name: 'bar').toThrow()
351
+ expect(console.error.calls.length).toBe 5
352
expect(console.error.calls[0].args[0]).toContain(
353
'getDOMNode(...) is deprecated in plain JavaScript React classes'
354
)
@@ -356,6 +358,12 @@ describe 'ReactCoffeeScriptClass', ->
358
expect(console.error.calls[2].args[0]).toContain(
359
'isMounted(...) is deprecated in plain JavaScript React classes'
360
)
361
+ expect(console.error.calls[3].args[0]).toContain(
362
+ 'setProps(...) is deprecated in plain JavaScript React classes'
363
+ )
364
+ expect(console.error.calls[4].args[0]).toContain(
365
+ 'replaceProps(...) is deprecated in plain JavaScript React classes'
366
+ )
367
368
it 'supports this.context passed via getChildContext', ->
369
class Bar
src/isomorphic/modern/class/__tests__/ReactES6Class-test.js
+9
-1
@@ -404,7 +404,9 @@ describe('ReactES6Class', function() {
404
expect(() => instance.getDOMNode()).toThrow();
405
expect(() => instance.replaceState({})).toThrow();
406
expect(() => instance.isMounted()).toThrow();
407
- expect(console.error.calls.length).toBe(3);
407
+ expect(() => instance.setProps({name: 'bar'})).toThrow();
408
+ expect(() => instance.replaceProps({name: 'bar'})).toThrow();
409
+ expect(console.error.calls.length).toBe(5);
410
expect(console.error.calls[0].args[0]).toContain(
411
'getDOMNode(...) is deprecated in plain JavaScript React classes. ' +
412
'Use React.findDOMNode(component) instead.'
@@ -415,6 +417,12 @@ describe('ReactES6Class', function() {
417
expect(console.error.calls[2].args[0]).toContain(
418
'isMounted(...) is deprecated in plain JavaScript React classes'
419
);
420
+ expect(console.error.calls[3].args[0]).toContain(
421
+ 'setProps(...) is deprecated in plain JavaScript React classes'
422
+ );
423
+ expect(console.error.calls[4].args[0]).toContain(
424
+ 'replaceProps(...) is deprecated in plain JavaScript React classes'
425
+ );
426
});
427
428
it('supports this.context passed via getChildContext', function() {
src/isomorphic/modern/class/__tests__/ReactTypeScriptClass-test.ts
+9
-1
@@ -492,7 +492,9 @@ describe('ReactTypeScriptClass', function() {
492
expect(() => instance.getDOMNode()).toThrow();
493
expect(() => instance.replaceState({})).toThrow();
494
expect(() => instance.isMounted()).toThrow();
495
- expect((<any>console.error).argsForCall.length).toBe(3);
495
+ expect(() => instance.setProps({ name: 'bar' })).toThrow();
496
+ expect(() => instance.replaceProps({ name: 'bar' })).toThrow();
497
+ expect((<any>console.error).argsForCall.length).toBe(5);
498
expect((<any>console.error).argsForCall[0][0]).toContain(
499
'getDOMNode(...) is deprecated in plain JavaScript React classes'
500
);
@@ -502,6 +504,12 @@ describe('ReactTypeScriptClass', function() {
504
expect((<any>console.error).argsForCall[2][0]).toContain(
505
'isMounted(...) is deprecated in plain JavaScript React classes'
506
);
507
+ expect((<any>console.error).argsForCall[3][0]).toContain(
508
+ 'setProps(...) is deprecated in plain JavaScript React classes'
509
+ );
510
+ expect((<any>console.error).argsForCall[4][0]).toContain(
511
+ 'replaceProps(...) is deprecated in plain JavaScript React classes'
512
+ );
513
});
514
515
it('supports this.context passed via getChildContext', function() {
src/renderers/dom/shared/ReactDOMComponent.js
+41
@@ -30,6 +30,7 @@ var ReactDOMTextarea = require('ReactDOMTextarea');
30
var ReactMount = require('ReactMount');
31
var ReactMultiChild = require('ReactMultiChild');
32
var ReactPerf = require('ReactPerf');
33
+var ReactUpdateQueue = require('ReactUpdateQueue');
34
35
var assign = require('Object.assign');
36
var escapeTextContentForBrowser = require('escapeTextContentForBrowser');
@@ -129,6 +130,44 @@ function legacySetStateEtc() {
130
}
131
}
132
133
+function legacySetProps(partialProps, callback) {
134
+ var component = this._reactInternalComponent;
135
+ if (__DEV__) {
136
+ warning(
137
+ false,
138
+ 'ReactDOMComponent: Do not access .setProps() of a DOM node. ' +
139
+ 'Instead, call React.render again at the top level.%s',
140
+ getDeclarationErrorAddendum(component)
141
+ );
142
+ }
143
+ if (!component) {
144
+ return;
145
+ }
146
+ ReactUpdateQueue.enqueueSetPropsInternal(component, partialProps);
147
+ if (callback) {
148
+ ReactUpdateQueue.enqueueCallbackInternal(component, callback);
149
+ }
150
+}
151
+
152
+function legacyReplaceProps(partialProps, callback) {
153
+ var component = this._reactInternalComponent;
154
+ if (__DEV__) {
155
+ warning(
156
+ false,
157
+ 'ReactDOMComponent: Do not access .replaceProps() of a DOM node. ' +
158
+ 'Instead, call React.render again at the top level.%s',
159
+ getDeclarationErrorAddendum(component)
160
+ );
161
+ }
162
+ if (!component) {
163
+ return;
164
+ }
165
+ ReactUpdateQueue.enqueueReplacePropsInternal(component, partialProps);
166
+ if (callback) {
167
+ ReactUpdateQueue.enqueueCallbackInternal(component, callback);
168
+ }
169
+}
170
+
171
var styleMutationWarning = {};
172
173
function checkAndWarnForMutatedStyle(style1, style2, component) {
@@ -919,6 +958,8 @@ ReactDOMComponent.Mixin = {
958
node.setState = legacySetStateEtc;
959
node.replaceState = legacySetStateEtc;
960
node.forceUpdate = legacySetStateEtc;
961
+ node.setProps = legacySetProps;
962
+ node.replaceProps = legacyReplaceProps;
963
964
if (__DEV__) {
965
if (canDefineProperty) {
src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js
+23
@@ -974,6 +974,29 @@ describe('ReactDOMComponent', function() {
974
expect(console.error.calls[4].args[0]).toContain('isMounted');
975
});
976
977
+ it('handles legacy setProps and replaceProps', function() {
978
+ spyOn(console, 'error');
979
+ var node = ReactTestUtils.renderIntoDocument(<div>rhinoceros</div>);
980
+
981
+ node.setProps({className: 'herbiverous'});
982
+ expect(node.className).toBe('herbiverous');
983
+ expect(node.textContent).toBe('rhinoceros');
984
+
985
+ node.replaceProps({className: 'invisible rhino'});
986
+ expect(node.className).toBe('invisible rhino');
987
+ expect(node.textContent).toBe('');
988
+
989
+ expect(console.error.calls.length).toBe(2);
990
+ expect(console.error.calls[0].args[0]).toBe(
991
+ 'Warning: ReactDOMComponent: Do not access .setProps() of a DOM node. ' +
992
+ 'Instead, call React.render again at the top level.'
993
+ );
994
+ expect(console.error.calls[1].args[0]).toBe(
995
+ 'Warning: ReactDOMComponent: Do not access .replaceProps() of a DOM ' +
996
+ 'node. Instead, call React.render again at the top level.'
997
+ );
998
+ });
999
+
1000
it('does not touch ref-less nodes', function() {
1001
var node = ReactTestUtils.renderIntoDocument(<div><span /></div>);
1002
expect(typeof node.getDOMNode).toBe('function');
src/renderers/shared/reconciler/ReactUpdateQueue.js
+89
-2
@@ -12,9 +12,11 @@
12
'use strict';
13
14
var ReactCurrentOwner = require('ReactCurrentOwner');
15
+var ReactElement = require('ReactElement');
16
var ReactInstanceMap = require('ReactInstanceMap');
17
var ReactUpdates = require('ReactUpdates');
18
19
+var assign = require('Object.assign');
20
var invariant = require('invariant');
21
var warning = require('warning');
22
@@ -106,7 +108,7 @@ var ReactUpdateQueue = {
108
enqueueCallback: function(publicInstance, callback) {
109
invariant(
110
typeof callback === 'function',
109
- 'enqueueCallback(...): You called ' +
111
+ 'enqueueCallback(...): You called `setProps`, `replaceProps`, ' +
112
'`setState`, `replaceState`, or `forceUpdate` with a callback that ' +
113
'isn\'t callable.'
114
);
@@ -136,7 +138,7 @@ var ReactUpdateQueue = {
138
enqueueCallbackInternal: function(internalInstance, callback) {
139
invariant(
140
typeof callback === 'function',
139
- 'enqueueCallback(...): You called ' +
141
+ 'enqueueCallback(...): You called `setProps`, `replaceProps`, ' +
142
'`setState`, `replaceState`, or `forceUpdate` with a callback that ' +
143
'isn\'t callable.'
144
);
@@ -231,6 +233,91 @@ var ReactUpdateQueue = {
233
enqueueUpdate(internalInstance);
234
},
235
236
+ /**
237
+ * Sets a subset of the props.
238
+ *
239
+ * @param {ReactClass} publicInstance The instance that should rerender.
240
+ * @param {object} partialProps Subset of the next props.
241
+ * @internal
242
+ */
243
+ enqueueSetProps: function(publicInstance, partialProps) {
244
+ var internalInstance = getInternalInstanceReadyForUpdate(
245
+ publicInstance,
246
+ 'setProps'
247
+ );
248
+ if (!internalInstance) {
249
+ return;
250
+ }
251
+ ReactUpdateQueue.enqueueSetPropsInternal(internalInstance, partialProps);
252
+ },
253
+
254
+ enqueueSetPropsInternal: function(internalInstance, partialProps) {
255
+ var topLevelWrapper = internalInstance._topLevelWrapper;
256
+ invariant(
257
+ topLevelWrapper,
258
+ 'setProps(...): You called `setProps` on a ' +
259
+ 'component with a parent. This is an anti-pattern since props will ' +
260
+ 'get reactively updated when rendered. Instead, change the owner\'s ' +
261
+ '`render` method to pass the correct value as props to the component ' +
262
+ 'where it is created.'
263
+ );
264
+
265
+ // Merge with the pending element if it exists, otherwise with existing
266
+ // element props.
267
+ var wrapElement = topLevelWrapper._pendingElement ||
268
+ topLevelWrapper._currentElement;
269
+ var element = wrapElement.props;
270
+ var props = assign({}, element.props, partialProps);
271
+ topLevelWrapper._pendingElement = ReactElement.cloneAndReplaceProps(
272
+ wrapElement,
273
+ ReactElement.cloneAndReplaceProps(element, props)
274
+ );
275
+
276
+ enqueueUpdate(topLevelWrapper);
277
+ },
278
+
279
+ /**
280
+ * Replaces all of the props.
281
+ *
282
+ * @param {ReactClass} publicInstance The instance that should rerender.
283
+ * @param {object} props New props.
284
+ * @internal
285
+ */
286
+ enqueueReplaceProps: function(publicInstance, props) {
287
+ var internalInstance = getInternalInstanceReadyForUpdate(
288
+ publicInstance,
289
+ 'replaceProps'
290
+ );
291
+ if (!internalInstance) {
292
+ return;
293
+ }
294
+ ReactUpdateQueue.enqueueReplacePropsInternal(internalInstance, props);
295
+ },
296
+
297
+ enqueueReplacePropsInternal: function(internalInstance, props) {
298
+ var topLevelWrapper = internalInstance._topLevelWrapper;
299
+ invariant(
300
+ topLevelWrapper,
301
+ 'replaceProps(...): You called `replaceProps` on a ' +
302
+ 'component with a parent. This is an anti-pattern since props will ' +
303
+ 'get reactively updated when rendered. Instead, change the owner\'s ' +
304
+ '`render` method to pass the correct value as props to the component ' +
305
+ 'where it is created.'
306
+ );
307
+
308
+ // Merge with the pending element if it exists, otherwise with existing
309
+ // element props.
310
+ var wrapElement = topLevelWrapper._pendingElement ||
311
+ topLevelWrapper._currentElement;
312
+ var element = wrapElement.props;
313
+ topLevelWrapper._pendingElement = ReactElement.cloneAndReplaceProps(
314
+ wrapElement,
315
+ ReactElement.cloneAndReplaceProps(element, props)
316
+ );
317
+
318
+ enqueueUpdate(topLevelWrapper);
319
+ },
320
+
321
enqueueElementInternal: function(internalInstance, newElement) {
322
internalInstance._pendingElement = newElement;
323
enqueueUpdate(internalInstance);
src/renderers/shared/reconciler/ReactUpdates.js
+1
-1
@@ -199,7 +199,7 @@ function enqueueUpdate(component) {
199
// Various parts of our code (such as ReactCompositeComponent's
200
// _renderValidatedComponent) assume that calls to render aren't nested;
201
// verify that that's the case. (This is called by each top-level update
202
- // function, like setState, forceUpdate, etc.; creation and
202
+ // function, like setProps, setState, forceUpdate, etc.; creation and
203
// destruction of top-level components is guarded in ReactMount.)
204
205
if (!batchingStrategy.isBatchingUpdates) {
src/renderers/shared/reconciler/__tests__/ReactComponentLifeCycle-test.js
+56
-10
@@ -442,6 +442,46 @@ describe('ReactComponentLifeCycle', function() {
442
expect(instance.state).toEqual(POST_WILL_UNMOUNT_STATE);
443
});
444
445
+ it('should throw when calling setProps() on an owned component', function() {
446
+ /**
447
+ * calls setProps in an componentDidMount.
448
+ */
449
+ var Inner = React.createClass({
450
+ render: function() {
451
+ return <div />;
452
+ },
453
+ });
454
+ var PropsUpdaterInOnDOMReady = React.createClass({
455
+ componentDidMount: function() {
456
+ this.refs.theSimpleComponent.setProps({
457
+ className: this.props.valueToUseInOnDOMReady,
458
+ });
459
+ },
460
+ render: function() {
461
+ return (
462
+ <Inner
463
+ className={this.props.valueToUseInitially}
464
+ ref="theSimpleComponent"
465
+ />
466
+ );
467
+ },
468
+ });
469
+ var instance =
470
+ <PropsUpdaterInOnDOMReady
471
+ valueToUseInitially="hello"
472
+ valueToUseInOnDOMReady="goodbye"
473
+ />;
474
+ expect(function() {
475
+ instance = ReactTestUtils.renderIntoDocument(instance);
476
+ }).toThrow(
477
+ 'Invariant Violation: setProps(...): You called `setProps` on a ' +
478
+ 'component with a parent. This is an anti-pattern since props will get ' +
479
+ 'reactively updated when rendered. Instead, change the owner\'s ' +
480
+ '`render` method to pass the correct value as props to the component ' +
481
+ 'where it is created.'
482
+ );
483
+ });
484
+
485
it('should not throw when updating an auxiliary component', function() {
486
var Tooltip = React.createClass({
487
render: function() {
@@ -472,18 +512,24 @@ describe('ReactComponentLifeCycle', function() {
512
},
513
});
514
475
- var container = document.createElement('div');
476
- React.render(
477
- <Component text="uno" tooltipText="one" />,
478
- container
515
+ var instance = ReactTestUtils.renderIntoDocument(
516
+ <Component text="uno" tooltipText="one" />
517
);
518
519
// Since `instance` is a root component, we can set its props. This also
520
// makes Tooltip rerender the tooltip component, which shouldn't throw.
483
- React.render(
484
- <Component text="dos" tooltipText="two" />,
485
- container
486
- );
521
+ instance.setProps({text: 'dos', tooltipText: 'two'});
522
+ });
523
+
524
+ it('should not allow setProps() called on an unmounted element',
525
+ function() {
526
+ var PropsToUpdate = React.createClass({
527
+ render: function() {
528
+ return <div className={this.props.value} ref="theSimpleComponent" />;
529
+ },
530
+ });
531
+ var instance = <PropsToUpdate value="hello" />;
532
+ expect(instance.setProps).not.toBeDefined();
533
});
534
535
it('should allow state updates in componentDidMount', function() {
@@ -549,7 +595,7 @@ describe('ReactComponentLifeCycle', function() {
595
596
var container = document.createElement('div');
597
log = [];
552
- React.render(<Outer x={17} />, container);
598
+ var instance = React.render(<Outer x={17} />, container);
599
expect(log).toEqual([
600
'outer componentWillMount',
601
'inner componentWillMount',
@@ -558,7 +604,7 @@ describe('ReactComponentLifeCycle', function() {
604
]);
605
606
log = [];
561
- React.render(<Outer x={42} />, container);
607
+ instance.setProps({x: 42});
608
expect(log).toEqual([
609
'outer componentWillReceiveProps',
610
'outer shouldComponentUpdate',
src/renderers/shared/reconciler/__tests__/ReactCompositeComponent-test.js
+71
-3
@@ -138,7 +138,10 @@ describe('ReactCompositeComponent', function() {
138
it('should not cache old DOM nodes when switching constructors', function() {
139
var instance = <ChildUpdates renderAnchor={true} anchorClassOn={false}/>;
140
instance = ReactTestUtils.renderIntoDocument(instance);
141
+ instance.setProps({anchorClassOn: true}); // Warm any cache
142
+ instance.setProps({renderAnchor: false}); // Clear out the anchor
143
// rerender
144
+ instance.setProps({renderAnchor: true, anchorClassOn: false});
145
var anchor = instance.getAnchor();
146
var actualDOMAnchorNode = React.findDOMNode(anchor);
147
expect(actualDOMAnchorNode.className).toBe('');
@@ -396,6 +399,72 @@ describe('ReactCompositeComponent', function() {
399
expect(instance2.state.value).toBe(1);
400
});
401
402
+ it('should not allow `setProps` on unmounted components', function() {
403
+ var container = document.createElement('div');
404
+ document.body.appendChild(container);
405
+
406
+ var Component = React.createClass({
407
+ render: function() {
408
+ return <div />;
409
+ },
410
+ });
411
+
412
+ var instance = <Component />;
413
+ expect(instance.setProps).not.toBeDefined();
414
+
415
+ instance = React.render(instance, container);
416
+ expect(function() {
417
+ instance.setProps({value: 1});
418
+ }).not.toThrow();
419
+ expect(console.error.calls.length).toBe(0);
420
+
421
+ React.unmountComponentAtNode(container);
422
+ expect(function() {
423
+ instance.setProps({value: 2});
424
+ }).not.toThrow();
425
+
426
+ expect(console.error.calls.length).toBe(1);
427
+ expect(console.error.argsForCall[0][0]).toBe(
428
+ 'Warning: setProps(...): Can only update a mounted or ' +
429
+ 'mounting component. This usually means you called setProps() on an ' +
430
+ 'unmounted component. This is a no-op. Please check the code for the ' +
431
+ 'Component component.'
432
+ );
433
+ });
434
+
435
+ it('should only allow `setProps` on top-level components', function() {
436
+ var container = document.createElement('div');
437
+ document.body.appendChild(container);
438
+
439
+ var innerInstance;
440
+
441
+ var Inner = React.createClass({
442
+ render: function() {
443
+ return <div />;
444
+ },
445
+ });
446
+ var Component = React.createClass({
447
+ render: function() {
448
+ return <div><Inner ref="inner" /></div>;
449
+ },
450
+ componentDidMount: function() {
451
+ innerInstance = this.refs.inner;
452
+ },
453
+ });
454
+ React.render(<Component />, container);
455
+
456
+ expect(innerInstance).not.toBe(undefined);
457
+ expect(function() {
458
+ innerInstance.setProps({value: 1});
459
+ }).toThrow(
460
+ 'Invariant Violation: setProps(...): You called `setProps` on a ' +
461
+ 'component with a parent. This is an anti-pattern since props will get ' +
462
+ 'reactively updated when rendered. Instead, change the owner\'s ' +
463
+ '`render` method to pass the correct value as props to the component ' +
464
+ 'where it is created.'
465
+ );
466
+ });
467
+
468
it('should cleanup even if render() fatals', function() {
469
var BadComponent = React.createClass({
470
render: function() {
@@ -866,8 +935,7 @@ describe('ReactCompositeComponent', function() {
935
},
936
});
937
869
- var container = document.createElement('div');
870
- var comp = React.render(<Component flipped={false} />, container);
938
+ var comp = ReactTestUtils.renderIntoDocument(<Component flipped={false} />);
939
expect(React.findDOMNode(comp.refs.static0).textContent).toBe('A');
940
expect(React.findDOMNode(comp.refs.static1).textContent).toBe('B');
941
@@ -878,7 +946,7 @@ describe('ReactCompositeComponent', function() {
946
947
// When flipping the order, the refs should update even though the actual
948
// contents do not
881
- React.render(<Component flipped={true} />, container);
949
+ comp.setProps({flipped: true});
950
expect(React.findDOMNode(comp.refs.static0).textContent).toBe('B');
951
expect(React.findDOMNode(comp.refs.static1).textContent).toBe('A');
952
src/renderers/shared/reconciler/__tests__/ReactCompositeComponentState-test.js
+2
-3
@@ -138,9 +138,8 @@ describe('ReactCompositeComponent-state', function() {
138
this.peekAtState('initial-callback');
139
}
140
);
141
- React.render(
142
- <TestComponent stateListener={stateListener} nextColor="green" />,
143
- container,
141
+ instance.setProps(
142
+ {nextColor: 'green'},
143
instance.peekAtCallback('setProps')
144
);
145
instance.setFavoriteColor('blue');
src/renderers/shared/reconciler/__tests__/ReactMultiChildReconcile-test.js
+8
-20
@@ -15,6 +15,7 @@ require('mock-modules');
15
16
var React = require('React');
17
var ReactInstanceMap = require('ReactInstanceMap');
18
+var ReactTestUtils = require('ReactTestUtils');
19
var ReactMount = require('ReactMount');
20
21
var mapObject = require('mapObject');
@@ -211,20 +212,15 @@ function verifyDomOrderingAccurate(parentInstance, statusDisplays) {
212
*/
213
function testPropsSequence(sequence) {
214
var i;
214
- var container = document.createElement('div');
215
- var parentInstance = React.render(
216
- <FriendsStatusDisplay {...sequence[0]} />,
217
- container
215
+ var parentInstance = ReactTestUtils.renderIntoDocument(
216
+ <FriendsStatusDisplay {...sequence[0]} />
217
);
218
var statusDisplays = parentInstance.getStatusDisplays();
219
var lastInternalStates = getInteralStateByUserName(statusDisplays);
220
verifyStatuses(statusDisplays, sequence[0]);
221
222
for (i = 1; i < sequence.length; i++) {
224
- React.render(
225
- <FriendsStatusDisplay {...sequence[i]} />,
226
- container
227
- );
223
+ parentInstance.replaceProps(sequence[i]);
224
statusDisplays = parentInstance.getStatusDisplays();
225
verifyStatuses(statusDisplays, sequence[i]);
226
verifyStatesPreserved(lastInternalStates, statusDisplays);
@@ -247,27 +243,19 @@ describe('ReactMultiChildReconcile', function() {
243
},
244
};
245
250
- var container = document.createElement('div');
251
- var parentInstance = React.render(
252
- <FriendsStatusDisplay {...props} />,
253
- container
246
+ var parentInstance = ReactTestUtils.renderIntoDocument(
247
+ <FriendsStatusDisplay {...props} />
248
);
249
var statusDisplays = parentInstance.getStatusDisplays();
250
var startingInternalState = statusDisplays.jcw.getInternalState();
251
252
// Now remove the child.
259
- React.render(
260
- <FriendsStatusDisplay />,
261
- container
262
- );
253
+ parentInstance.replaceProps({usernameToStatus: {} });
254
statusDisplays = parentInstance.getStatusDisplays();
255
expect(statusDisplays.jcw).toBeFalsy();
256
257
// Now reset the props that cause there to be a child
267
- React.render(
268
- <FriendsStatusDisplay {...props} />,
269
- container
270
- );
258
+ parentInstance.replaceProps(props);
259
statusDisplays = parentInstance.getStatusDisplays();
260
expect(statusDisplays.jcw).toBeTruthy();
261
expect(statusDisplays.jcw.getInternalState())
src/renderers/shared/reconciler/__tests__/ReactUpdates-test.js
+2
@@ -100,12 +100,14 @@ describe('ReactUpdates', function() {
100
expect(instance.state.y).toBe(0);
101
102
ReactUpdates.batchedUpdates(function() {
103
+ instance.setProps({x: 1});
104
instance.setState({y: 2});
105
expect(instance.props.x).toBe(0);
106
expect(instance.state.y).toBe(0);
107
expect(updateCount).toBe(0);
108
});
109
110
+ expect(instance.props.x).toBe(1);
111
expect(instance.state.y).toBe(2);
112
expect(updateCount).toBe(1);
113
});