Skip to content

Commit

Permalink
Add support for out-of-order render client side (#948)
Browse files Browse the repository at this point in the history
React Server assumes that it can render in-order client side since the data
required to render each element will necessarily have arrived by the time it
is reached. In order to support moving the JS for non-critical above-the-fold
components into a secondary bundle, though, we would need support for
out-of-order rendering in the browser.
  • Loading branch information
gigabo authored Sep 8, 2017
1 parent 6b96e0b commit d3a7777
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 9 deletions.
4 changes: 4 additions & 0 deletions packages/react-server-test-pages/entrypoints.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ module.exports = {
entry: "/root/when",
description: "<RootElement when={...}>",
},
RootOrder: {
entry: "/root/order",
description: "Out of order render",
},
RootProvider: {
entry: "/root/rootProvider",
description: "<RootProvider store={...}>",
Expand Down
35 changes: 35 additions & 0 deletions packages/react-server-test-pages/pages/root/order.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {Component} from "react";
import {RootElement} from "react-server";
import Q from "q";

class TurnGreen extends Component {
componentDidMount() {
this.setState({color: "green"});
}
render() {
const {color} = this.state || {};
return <div style={{backgroundColor: color || "red"}}>{this.props.children}</div>;
}
}

export default class RootOrderPage {
handleRoute(next) {
this.first = this.second = Q();

if (typeof window !== "undefined") {
this.first = Q.delay(1000);
}

return next();
}
getElements() {
return [
<RootElement when={this.first}>
<TurnGreen>This should turn green second</TurnGreen>
</RootElement>,
<RootElement when={this.second}>
<TurnGreen>This should turn green first</TurnGreen>
</RootElement>,
]
}
}
13 changes: 4 additions & 9 deletions packages/react-server/core/ClientController.js
Original file line number Diff line number Diff line change
Expand Up @@ -604,12 +604,8 @@ class ClientController extends EventEmitter {
// As elements become ready, prime them to render as soon as
// their mount point is available.
//
// Always render in order to proritize content higher in the
// page.
//
elementPromisesOr.reduce((chain, promise, index) => chain
.then(() => promise
.then(element => rootNodePromises[index]
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
Expand All @@ -619,9 +615,8 @@ class ClientController extends EventEmitter {
: 'element';
logger.error(`Error with element ${componentType}'s lifecycle methods at index ${index}`, e);
})
).catch(e => logger.error(`Error with element promise ${index}`, e))
),
Q()).then(retval.resolve);
).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.
Expand Down

0 comments on commit d3a7777

Please sign in to comment.