Skip to content

Commit

Permalink
Client transitions still need to render in order (#962)
Browse files Browse the repository at this point in the history
During client transitions the root structure is built up using a state machine
that requires an in-order render. First render can still go out of order
because the server has already laid out the root structure.

This fixes #961.
  • Loading branch information
gigabo authored Oct 17, 2017
1 parent 13d6f25 commit 262812a
Showing 1 changed file with 29 additions and 20 deletions.
49 changes: 29 additions & 20 deletions packages/react-server/core/ClientController.js
Original file line number Diff line number Diff line change
Expand Up @@ -601,26 +601,35 @@ class ClientController extends EventEmitter {
}
};

// As elements become ready, prime them to render as soon as
// their mount point is available.
//
Q.all(elementPromisesOr.map((promise, index) => promise.then(
element => rootNodePromises[index]
.then(root => renderElement(element, root, index))
.catch(e => {
// The only case where this should evaluate to false is
// when `element` is a containerClose/containerOpen object
const componentType = typeof element.type === 'function'
? element.props.children.type.name
: 'element';
logger.error(`Error with element ${componentType}'s lifecycle methods at index ${index}`, e);
})
).catch(e => logger.error(`Error with element promise ${index}`, e))
)).then(retval.resolve);

// Look out for a failsafe timeout from the server on our
// first render.
if (!this._previouslyRendered){
const renderOne = (promise, index) => promise.then(
element => rootNodePromises[index]
.then(root => renderElement(element, root, index))
.catch(e => {
// The only case where this should evaluate to false is
// when `element` is a containerClose/containerOpen object
const componentType = typeof element.type === 'function'
? element.props.children.type.name
: 'element';
logger.error(`Error with element ${componentType}'s lifecycle methods at index ${index}`, e);
})
).catch(e => logger.error(`Error with element promise ${index}`, e))

if (this._previouslyRendered){

// On client transitions the root structure is laid out using a
// state machine that requires us to render in order.
elementPromisesOr.reduce(
(chain, promise, index) => chain.then(() => renderOne(promise, index)),
Q()
).then(retval.resolve);
} else {

// On the first render we can go out of order because the server
// has already laid out the root structure for us.
Q.all(elementPromisesOr.map(renderOne)).then(retval.resolve);

// Look out for a failsafe timeout from the server on our
// first render.
this._failDfd.promise.then(() => {
elementPromises.forEach((promise, index) => {
//Reject any elements that have failed to render
Expand Down

0 comments on commit 262812a

Please sign in to comment.