@samitouri / QOS-React / commits / ae430b7913

React.unstable_AsyncComponent (#10239)

Alternative to using the static class property unstable_asyncUpdates. Everything inside <AsyncComponent /> has async updates by default. You can also extend it like PureComponent or Component.

Andrew Clark committed Jul 20, 2017 at 18:00 UTC ae430b79139777b74167b124719b3dc311aa5294
6 files changed +57 -38
scripts/fiber/tests-passing.txt
+2 -2
@@ -674,9 +674,9 @@ src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js
674 src/renderers/dom/fiber/__tests__/ReactDOMFiberAsync-test.js
675 * renders synchronously by default
676 * renders synchronously when feature flag is disabled
677 -* unstable_asyncUpdates at the root makes the entire tree async
677 +* AsyncComponent at the root makes the entire tree async
678 * updates inside an async tree are async by default
679 -* unstable_asyncUpdates creates an async subtree
679 +* AsyncComponent creates an async subtree
680 * updates inside an async subtree are async by default
681
682 src/renderers/dom/shared/__tests__/CSSProperty-test.js
src/isomorphic/ReactEntry.js
+1
@@ -40,6 +40,7 @@ var React = {
40
41 Component: ReactBaseClasses.Component,
42 PureComponent: ReactBaseClasses.PureComponent,
43 + unstable_AsyncComponent: ReactBaseClasses.AsyncComponent,
44
45 createElement: createElement,
46 cloneElement: cloneElement,
src/isomorphic/modern/class/ReactBaseClasses.js
+24 -4
@@ -138,13 +138,33 @@ function ReactPureComponent(props, context, updater) {
138
139 function ComponentDummy() {}
140 ComponentDummy.prototype = ReactComponent.prototype;
141 -ReactPureComponent.prototype = new ComponentDummy();
142 -ReactPureComponent.prototype.constructor = ReactPureComponent;
141 +var pureComponentPrototype = (ReactPureComponent.prototype = new ComponentDummy());
142 +pureComponentPrototype.constructor = ReactPureComponent;
143 // Avoid an extra prototype jump for these methods.
144 -Object.assign(ReactPureComponent.prototype, ReactComponent.prototype);
145 -ReactPureComponent.prototype.isPureReactComponent = true;
144 +Object.assign(pureComponentPrototype, ReactComponent.prototype);
145 +pureComponentPrototype.isPureReactComponent = true;
146 +
147 +function ReactAsyncComponent(props, context, updater) {
148 + // Duplicated from ReactComponent.
149 + this.props = props;
150 + this.context = context;
151 + this.refs = emptyObject;
152 + // We initialize the default updater but the real one gets injected by the
153 + // renderer.
154 + this.updater = updater || ReactNoopUpdateQueue;
155 +}
156 +
157 +var asyncComponentPrototype = (ReactAsyncComponent.prototype = new ComponentDummy());
158 +asyncComponentPrototype.constructor = ReactAsyncComponent;
159 +// Avoid an extra prototype jump for these methods.
160 +Object.assign(asyncComponentPrototype, ReactComponent.prototype);
161 +asyncComponentPrototype.unstable_isAsyncReactComponent = true;
162 +asyncComponentPrototype.render = function() {
163 + return this.props.children;
164 +};
165
166 module.exports = {
167 Component: ReactComponent,
168 PureComponent: ReactPureComponent,
169 + AsyncComponent: ReactAsyncComponent,
170 };
src/renderers/dom/fiber/__tests__/ReactDOMFiberAsync-test.js
+26 -30
@@ -4,6 +4,8 @@ var ReactFeatureFlags = require('ReactFeatureFlags');
4
5 var ReactDOM;
6
7 +var AsyncComponent = React.unstable_AsyncComponent;
8 +
9 describe('ReactDOMFiberAsync', () => {
10 var container;
11
@@ -25,16 +27,16 @@ describe('ReactDOMFiberAsync', () => {
27
28 if (ReactDOMFeatureFlags.useFiber) {
29 it('renders synchronously when feature flag is disabled', () => {
28 - class Async extends React.Component {
29 - static unstable_asyncUpdates = true;
30 - render() {
31 - return this.props.children;
32 - }
33 - }
34 - ReactDOM.render(<Async><div>Hi</div></Async>, container);
30 + ReactDOM.render(
31 + <AsyncComponent><div>Hi</div></AsyncComponent>,
32 + container,
33 + );
34 expect(container.textContent).toEqual('Hi');
35
37 - ReactDOM.render(<Async><div>Bye</div></Async>, container);
36 + ReactDOM.render(
37 + <AsyncComponent><div>Bye</div></AsyncComponent>,
38 + container,
39 + );
40 expect(container.textContent).toEqual('Bye');
41 });
42
@@ -47,32 +49,25 @@ describe('ReactDOMFiberAsync', () => {
49 ReactDOM = require('react-dom');
50 });
51
50 - it('unstable_asyncUpdates at the root makes the entire tree async', () => {
51 - class Async extends React.Component {
52 - static unstable_asyncUpdates = true;
53 - render() {
54 - return this.props.children;
55 - }
56 - }
57 - ReactDOM.render(<Async><div>Hi</div></Async>, container);
52 + it('AsyncComponent at the root makes the entire tree async', () => {
53 + ReactDOM.render(
54 + <AsyncComponent><div>Hi</div></AsyncComponent>,
55 + container,
56 + );
57 expect(container.textContent).toEqual('');
58 jest.runAllTimers();
59 expect(container.textContent).toEqual('Hi');
60
62 - ReactDOM.render(<Async><div>Bye</div></Async>, container);
61 + ReactDOM.render(
62 + <AsyncComponent><div>Bye</div></AsyncComponent>,
63 + container,
64 + );
65 expect(container.textContent).toEqual('Hi');
66 jest.runAllTimers();
67 expect(container.textContent).toEqual('Bye');
68 });
69
70 it('updates inside an async tree are async by default', () => {
69 - class Async extends React.Component {
70 - static unstable_asyncUpdates = true;
71 - render() {
72 - return this.props.children;
73 - }
74 - }
75 -
71 let instance;
72 class Component extends React.Component {
73 state = {step: 0};
@@ -82,7 +77,10 @@ describe('ReactDOMFiberAsync', () => {
77 }
78 }
79
85 - ReactDOM.render(<Async><Component /></Async>, container);
80 + ReactDOM.render(
81 + <AsyncComponent><Component /></AsyncComponent>,
82 + container,
83 + );
84 expect(container.textContent).toEqual('');
85 jest.runAllTimers();
86 expect(container.textContent).toEqual('0');
@@ -93,11 +91,10 @@ describe('ReactDOMFiberAsync', () => {
91 expect(container.textContent).toEqual('1');
92 });
93
96 - it('unstable_asyncUpdates creates an async subtree', () => {
94 + it('AsyncComponent creates an async subtree', () => {
95 let instance;
98 - class Component extends React.Component {
96 + class Component extends React.unstable_AsyncComponent {
97 state = {step: 0};
100 - static unstable_asyncUpdates = true;
98 render() {
99 instance = this;
100 return <div>{this.state.step}</div>;
@@ -114,8 +111,7 @@ describe('ReactDOMFiberAsync', () => {
111 });
112
113 it('updates inside an async subtree are async by default', () => {
117 - class Component extends React.Component {
118 - static unstable_asyncUpdates = true;
114 + class Component extends React.unstable_AsyncComponent {
115 render() {
116 return <Child />;
117 }
src/renderers/shared/fiber/ReactFiberClassComponent.js
+2 -1
@@ -388,7 +388,8 @@ module.exports = function(
388 if (
389 ReactFeatureFlags.enableAsyncSubtreeAPI &&
390 workInProgress.type != null &&
391 - workInProgress.type.unstable_asyncUpdates === true
391 + workInProgress.type.prototype != null &&
392 + workInProgress.type.prototype.unstable_isAsyncReactComponent === true
393 ) {
394 workInProgress.internalContextTag |= AsyncUpdates;
395 }
src/renderers/shared/fiber/ReactFiberReconciler.js
+2 -1
@@ -225,7 +225,8 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
225 ReactFeatureFlags.enableAsyncSubtreeAPI &&
226 element != null &&
227 element.type != null &&
228 - (element.type: any).unstable_asyncUpdates === true;
228 + element.type.prototype != null &&
229 + (element.type.prototype: any).unstable_isAsyncReactComponent === true;
230 const priorityLevel = getPriorityContext(current, forceAsync);
231 const nextState = {element};
232 callback = callback === undefined ? null : callback;