mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Don't initialize reconcile transaction on server
...when calling setState from within a componentWillMount. Fixes #1866.
Test Plan: jest
(cherry picked from commit 54d91c293d)
This commit is contained in:
committed by
Paul O’Shannessy
parent
975ce371e8
commit
df0a678fbb
@@ -31,12 +31,13 @@ require('mock-modules')
|
||||
|
||||
var mocks = require('mocks');
|
||||
|
||||
var ExecutionEnvironment;
|
||||
var React;
|
||||
var ReactMarkupChecksum;
|
||||
var ReactMount;
|
||||
var ReactReconcileTransaction;
|
||||
var ReactTestUtils;
|
||||
var ReactServerRendering;
|
||||
var ReactMarkupChecksum;
|
||||
var ExecutionEnvironment;
|
||||
|
||||
var ID_ATTRIBUTE_NAME;
|
||||
|
||||
@@ -44,12 +45,14 @@ describe('ReactServerRendering', function() {
|
||||
beforeEach(function() {
|
||||
require('mock-modules').dumpCache();
|
||||
React = require('React');
|
||||
ReactMarkupChecksum = require('ReactMarkupChecksum');
|
||||
ReactMount = require('ReactMount');
|
||||
ReactTestUtils = require('ReactTestUtils');
|
||||
ReactReconcileTransaction = require('ReactReconcileTransaction');
|
||||
|
||||
ExecutionEnvironment = require('ExecutionEnvironment');
|
||||
ExecutionEnvironment.canUseDOM = false;
|
||||
ReactServerRendering = require('ReactServerRendering');
|
||||
ReactMarkupChecksum = require('ReactMarkupChecksum');
|
||||
|
||||
var DOMProperty = require('DOMProperty');
|
||||
ID_ATTRIBUTE_NAME = DOMProperty.ID_ATTRIBUTE_NAME;
|
||||
@@ -373,5 +376,25 @@ describe('ReactServerRendering', function() {
|
||||
'a valid ReactComponent.'
|
||||
);
|
||||
});
|
||||
|
||||
it('allows setState in componentWillMount without using DOM', function() {
|
||||
var Component = React.createClass({
|
||||
componentWillMount: function() {
|
||||
this.setState({text: 'hello, world'});
|
||||
},
|
||||
render: function() {
|
||||
return <div>{this.state.text}</div>;
|
||||
}
|
||||
});
|
||||
|
||||
ReactReconcileTransaction.prototype.perform = function() {
|
||||
// We shouldn't ever be calling this on the server
|
||||
throw new Error('Browser reconcile transaction should not be used');
|
||||
};
|
||||
var markup = ReactServerRendering.renderComponentToString(
|
||||
<Component />
|
||||
);
|
||||
expect(markup.indexOf('hello, world') >= 0).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -172,6 +172,25 @@ var flushBatchedUpdates = ReactPerf.measure(
|
||||
// componentDidUpdate) but we need to check here too in order to catch
|
||||
// updates enqueued by setState callbacks.
|
||||
while (dirtyComponents.length) {
|
||||
var allUnmounted = true;
|
||||
for (var i = 0, l = dirtyComponents.length; i < l; i++) {
|
||||
if (dirtyComponents[i].isMounted()) {
|
||||
allUnmounted = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (allUnmounted) {
|
||||
// All the "dirty" components are unmounted, which probably means that
|
||||
// they were marked dirty due to setState calls in componentWillMount
|
||||
// handlers and the components are currently in the process of mounting.
|
||||
// `runBatchedUpdates` will be a noop. In that case, initializing the
|
||||
// DOM-dependent ReactReconcileTransaction is thus not what we want to
|
||||
// do, especially when using server rendering, so we skip it.
|
||||
dirtyComponents.length = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
var transaction = ReactUpdatesFlushTransaction.getPooled();
|
||||
transaction.perform(runBatchedUpdates, null, transaction);
|
||||
ReactUpdatesFlushTransaction.release(transaction);
|
||||
|
||||
Reference in New Issue
Block a user