mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Batch updates in initial render
Currently, the first setState that happens during initial render will start a new batch. Any subsequent updates will be batched. That means that the first setState is synchronous but any subsequent setStates are asynchronous. This commit makes it so that the batching starts at the root. That way all the setStates that happen within life-cycle methods are asynchronous.
This commit is contained in:
@@ -31,8 +31,8 @@ var ReactRAFBatchingStrategy = {
|
||||
* Call the provided function in a context within which calls to `setState`
|
||||
* and friends are batched such that components aren't updated unnecessarily.
|
||||
*/
|
||||
batchedUpdates: function(callback, a, b) {
|
||||
callback(a, b);
|
||||
batchedUpdates: function(callback, a, b, c, d) {
|
||||
callback(a, b, c, d);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -233,23 +233,51 @@ function findDeepestCachedAncestor(targetID) {
|
||||
/**
|
||||
* Mounts this component and inserts it into the DOM.
|
||||
*
|
||||
* @param {ReactComponent} componentInstance The instance to mount.
|
||||
* @param {string} rootID DOM ID of the root node.
|
||||
* @param {DOMElement} container DOM element to mount into.
|
||||
* @param {ReactReconcileTransaction} transaction
|
||||
* @param {boolean} shouldReuseMarkup If true, do not insert markup
|
||||
*/
|
||||
function mountComponentIntoNode(
|
||||
componentInstance,
|
||||
rootID,
|
||||
container,
|
||||
transaction,
|
||||
shouldReuseMarkup) {
|
||||
var markup = ReactReconciler.mountComponent(
|
||||
this, rootID, transaction, emptyObject
|
||||
componentInstance, rootID, transaction, emptyObject
|
||||
);
|
||||
this._isTopLevel = true;
|
||||
componentInstance._isTopLevel = true;
|
||||
ReactMount._mountImageIntoNode(markup, container, shouldReuseMarkup);
|
||||
}
|
||||
|
||||
/**
|
||||
* Batched mount.
|
||||
*
|
||||
* @param {ReactComponent} componentInstance The instance to mount.
|
||||
* @param {string} rootID DOM ID of the root node.
|
||||
* @param {DOMElement} container DOM element to mount into.
|
||||
* @param {boolean} shouldReuseMarkup If true, do not insert markup
|
||||
*/
|
||||
function batchedMountComponentIntoNode(
|
||||
componentInstance,
|
||||
rootID,
|
||||
container,
|
||||
shouldReuseMarkup) {
|
||||
var transaction = ReactUpdates.ReactReconcileTransaction.getPooled();
|
||||
transaction.perform(
|
||||
mountComponentIntoNode,
|
||||
null,
|
||||
componentInstance,
|
||||
rootID,
|
||||
container,
|
||||
transaction,
|
||||
shouldReuseMarkup
|
||||
);
|
||||
ReactUpdates.ReactReconcileTransaction.release(transaction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mounting is the process of initializing a React component by creatings its
|
||||
* representative DOM elements and inserting them into a supplied `container`.
|
||||
@@ -368,16 +396,17 @@ var ReactMount = {
|
||||
container
|
||||
);
|
||||
|
||||
var transaction = ReactUpdates.ReactReconcileTransaction.getPooled();
|
||||
transaction.perform(
|
||||
mountComponentIntoNode,
|
||||
// The initial render is synchronous but any updates that happen during
|
||||
// rendering, in componentWillMount or componentDidMount, will be batched
|
||||
// according to the current batching strategy.
|
||||
|
||||
ReactUpdates.batchedUpdates(
|
||||
batchedMountComponentIntoNode,
|
||||
componentInstance,
|
||||
reactRootID,
|
||||
container,
|
||||
transaction,
|
||||
shouldReuseMarkup
|
||||
);
|
||||
ReactUpdates.ReactReconcileTransaction.release(transaction);
|
||||
|
||||
if (__DEV__) {
|
||||
// Record the root element in case it later gets transplanted.
|
||||
|
||||
@@ -54,16 +54,16 @@ var ReactDefaultBatchingStrategy = {
|
||||
* Call the provided function in a context within which calls to `setState`
|
||||
* and friends are batched such that components aren't updated unnecessarily.
|
||||
*/
|
||||
batchedUpdates: function(callback, a, b) {
|
||||
batchedUpdates: function(callback, a, b, c, d) {
|
||||
var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates;
|
||||
|
||||
ReactDefaultBatchingStrategy.isBatchingUpdates = true;
|
||||
|
||||
// The code is written this way to avoid extra allocations
|
||||
if (alreadyBatchingUpdates) {
|
||||
callback(a, b);
|
||||
callback(a, b, c, d);
|
||||
} else {
|
||||
transaction.perform(callback, null, a, b);
|
||||
transaction.perform(callback, null, a, b, c, d);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -104,9 +104,9 @@ assign(
|
||||
|
||||
PooledClass.addPoolingTo(ReactUpdatesFlushTransaction);
|
||||
|
||||
function batchedUpdates(callback, a, b) {
|
||||
function batchedUpdates(callback, a, b, c, d) {
|
||||
ensureInjected();
|
||||
batchingStrategy.batchedUpdates(callback, a, b);
|
||||
batchingStrategy.batchedUpdates(callback, a, b, c, d);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -155,9 +155,9 @@ describe('ReactCompositeComponent-state', function() {
|
||||
[ 'componentDidMount-start', 'orange', null ],
|
||||
// setState-sunrise and setState-orange should be called here,
|
||||
// after the bug in #1740
|
||||
// componentDidMount() called setState({color:'yellow'}), currently this
|
||||
// occurs inline.
|
||||
// In a future where setState() is async, this test result will change.
|
||||
// componentDidMount() called setState({color:'yellow'}), which is async.
|
||||
// The update doesn't happen until the next flush.
|
||||
[ 'componentDidMount-end', 'orange', 'yellow' ],
|
||||
[ 'shouldComponentUpdate-currentState', 'orange', null ],
|
||||
[ 'shouldComponentUpdate-nextState', 'yellow' ],
|
||||
[ 'componentWillUpdate-currentState', 'orange', null ],
|
||||
@@ -166,8 +166,6 @@ describe('ReactCompositeComponent-state', function() {
|
||||
[ 'componentDidUpdate-currentState', 'yellow', null ],
|
||||
[ 'componentDidUpdate-prevState', 'orange' ],
|
||||
[ 'setState-yellow', 'yellow', null ],
|
||||
// componentDidMount() finally closes.
|
||||
[ 'componentDidMount-end', 'yellow', null ],
|
||||
[ 'initial-callback', 'yellow', null ],
|
||||
[ 'componentWillReceiveProps-start', 'yellow', null ],
|
||||
// setState({color:'green'}) only enqueues a pending state.
|
||||
|
||||
Reference in New Issue
Block a user