Skip to content

Commit ae430b7

Browse files
authored
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.
1 parent 9d248e0 commit ae430b7

File tree

6 files changed

+57
-38
lines changed

6 files changed

+57
-38
lines changed

scripts/fiber/tests-passing.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -674,9 +674,9 @@ src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js
674674
src/renderers/dom/fiber/__tests__/ReactDOMFiberAsync-test.js
675675
* renders synchronously by default
676676
* 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
678678
* updates inside an async tree are async by default
679-
* unstable_asyncUpdates creates an async subtree
679+
* AsyncComponent creates an async subtree
680680
* updates inside an async subtree are async by default
681681

682682
src/renderers/dom/shared/__tests__/CSSProperty-test.js

src/isomorphic/ReactEntry.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ var React = {
4040

4141
Component: ReactBaseClasses.Component,
4242
PureComponent: ReactBaseClasses.PureComponent,
43+
unstable_AsyncComponent: ReactBaseClasses.AsyncComponent,
4344

4445
createElement: createElement,
4546
cloneElement: cloneElement,

src/isomorphic/modern/class/ReactBaseClasses.js

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,13 +138,33 @@ function ReactPureComponent(props, context, updater) {
138138

139139
function ComponentDummy() {}
140140
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;
143143
// 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+
};
146165

147166
module.exports = {
148167
Component: ReactComponent,
149168
PureComponent: ReactPureComponent,
169+
AsyncComponent: ReactAsyncComponent,
150170
};

src/renderers/dom/fiber/__tests__/ReactDOMFiberAsync-test.js

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ var ReactFeatureFlags = require('ReactFeatureFlags');
44

55
var ReactDOM;
66

7+
var AsyncComponent = React.unstable_AsyncComponent;
8+
79
describe('ReactDOMFiberAsync', () => {
810
var container;
911

@@ -25,16 +27,16 @@ describe('ReactDOMFiberAsync', () => {
2527

2628
if (ReactDOMFeatureFlags.useFiber) {
2729
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+
);
3534
expect(container.textContent).toEqual('Hi');
3635

37-
ReactDOM.render(<Async><div>Bye</div></Async>, container);
36+
ReactDOM.render(
37+
<AsyncComponent><div>Bye</div></AsyncComponent>,
38+
container,
39+
);
3840
expect(container.textContent).toEqual('Bye');
3941
});
4042

@@ -47,32 +49,25 @@ describe('ReactDOMFiberAsync', () => {
4749
ReactDOM = require('react-dom');
4850
});
4951

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+
);
5857
expect(container.textContent).toEqual('');
5958
jest.runAllTimers();
6059
expect(container.textContent).toEqual('Hi');
6160

62-
ReactDOM.render(<Async><div>Bye</div></Async>, container);
61+
ReactDOM.render(
62+
<AsyncComponent><div>Bye</div></AsyncComponent>,
63+
container,
64+
);
6365
expect(container.textContent).toEqual('Hi');
6466
jest.runAllTimers();
6567
expect(container.textContent).toEqual('Bye');
6668
});
6769

6870
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-
7671
let instance;
7772
class Component extends React.Component {
7873
state = {step: 0};
@@ -82,7 +77,10 @@ describe('ReactDOMFiberAsync', () => {
8277
}
8378
}
8479

85-
ReactDOM.render(<Async><Component /></Async>, container);
80+
ReactDOM.render(
81+
<AsyncComponent><Component /></AsyncComponent>,
82+
container,
83+
);
8684
expect(container.textContent).toEqual('');
8785
jest.runAllTimers();
8886
expect(container.textContent).toEqual('0');
@@ -93,11 +91,10 @@ describe('ReactDOMFiberAsync', () => {
9391
expect(container.textContent).toEqual('1');
9492
});
9593

96-
it('unstable_asyncUpdates creates an async subtree', () => {
94+
it('AsyncComponent creates an async subtree', () => {
9795
let instance;
98-
class Component extends React.Component {
96+
class Component extends React.unstable_AsyncComponent {
9997
state = {step: 0};
100-
static unstable_asyncUpdates = true;
10198
render() {
10299
instance = this;
103100
return <div>{this.state.step}</div>;
@@ -114,8 +111,7 @@ describe('ReactDOMFiberAsync', () => {
114111
});
115112

116113
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 {
119115
render() {
120116
return <Child />;
121117
}

src/renderers/shared/fiber/ReactFiberClassComponent.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,8 @@ module.exports = function(
388388
if (
389389
ReactFeatureFlags.enableAsyncSubtreeAPI &&
390390
workInProgress.type != null &&
391-
workInProgress.type.unstable_asyncUpdates === true
391+
workInProgress.type.prototype != null &&
392+
workInProgress.type.prototype.unstable_isAsyncReactComponent === true
392393
) {
393394
workInProgress.internalContextTag |= AsyncUpdates;
394395
}

src/renderers/shared/fiber/ReactFiberReconciler.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,8 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(
225225
ReactFeatureFlags.enableAsyncSubtreeAPI &&
226226
element != null &&
227227
element.type != null &&
228-
(element.type: any).unstable_asyncUpdates === true;
228+
element.type.prototype != null &&
229+
(element.type.prototype: any).unstable_isAsyncReactComponent === true;
229230
const priorityLevel = getPriorityContext(current, forceAsync);
230231
const nextState = {element};
231232
callback = callback === undefined ? null : callback;

0 commit comments

Comments
 (0)