diff --git a/scripts/fiber/tests-passing.txt b/scripts/fiber/tests-passing.txt index f599832df086c..13b506ef68c02 100644 --- a/scripts/fiber/tests-passing.txt +++ b/scripts/fiber/tests-passing.txt @@ -674,9 +674,9 @@ src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js src/renderers/dom/fiber/__tests__/ReactDOMFiberAsync-test.js * renders synchronously by default * renders synchronously when feature flag is disabled -* unstable_asyncUpdates at the root makes the entire tree async +* AsyncComponent at the root makes the entire tree async * updates inside an async tree are async by default -* unstable_asyncUpdates creates an async subtree +* AsyncComponent creates an async subtree * updates inside an async subtree are async by default src/renderers/dom/shared/__tests__/CSSProperty-test.js diff --git a/src/isomorphic/ReactEntry.js b/src/isomorphic/ReactEntry.js index 2a89505003f37..e6ecd54048e03 100644 --- a/src/isomorphic/ReactEntry.js +++ b/src/isomorphic/ReactEntry.js @@ -40,6 +40,7 @@ var React = { Component: ReactBaseClasses.Component, PureComponent: ReactBaseClasses.PureComponent, + unstable_AsyncComponent: ReactBaseClasses.AsyncComponent, createElement: createElement, cloneElement: cloneElement, diff --git a/src/isomorphic/modern/class/ReactBaseClasses.js b/src/isomorphic/modern/class/ReactBaseClasses.js index a514b74de1d59..f2b3a6c6d6a6a 100644 --- a/src/isomorphic/modern/class/ReactBaseClasses.js +++ b/src/isomorphic/modern/class/ReactBaseClasses.js @@ -138,13 +138,33 @@ function ReactPureComponent(props, context, updater) { function ComponentDummy() {} ComponentDummy.prototype = ReactComponent.prototype; -ReactPureComponent.prototype = new ComponentDummy(); -ReactPureComponent.prototype.constructor = ReactPureComponent; +var pureComponentPrototype = (ReactPureComponent.prototype = new ComponentDummy()); +pureComponentPrototype.constructor = ReactPureComponent; // Avoid an extra prototype jump for these methods. -Object.assign(ReactPureComponent.prototype, ReactComponent.prototype); -ReactPureComponent.prototype.isPureReactComponent = true; +Object.assign(pureComponentPrototype, ReactComponent.prototype); +pureComponentPrototype.isPureReactComponent = true; + +function ReactAsyncComponent(props, context, updater) { + // Duplicated from ReactComponent. + this.props = props; + this.context = context; + this.refs = emptyObject; + // We initialize the default updater but the real one gets injected by the + // renderer. + this.updater = updater || ReactNoopUpdateQueue; +} + +var asyncComponentPrototype = (ReactAsyncComponent.prototype = new ComponentDummy()); +asyncComponentPrototype.constructor = ReactAsyncComponent; +// Avoid an extra prototype jump for these methods. +Object.assign(asyncComponentPrototype, ReactComponent.prototype); +asyncComponentPrototype.unstable_isAsyncReactComponent = true; +asyncComponentPrototype.render = function() { + return this.props.children; +}; module.exports = { Component: ReactComponent, PureComponent: ReactPureComponent, + AsyncComponent: ReactAsyncComponent, }; diff --git a/src/renderers/dom/fiber/__tests__/ReactDOMFiberAsync-test.js b/src/renderers/dom/fiber/__tests__/ReactDOMFiberAsync-test.js index a667aea7f2257..b81789caaadce 100644 --- a/src/renderers/dom/fiber/__tests__/ReactDOMFiberAsync-test.js +++ b/src/renderers/dom/fiber/__tests__/ReactDOMFiberAsync-test.js @@ -4,6 +4,8 @@ var ReactFeatureFlags = require('ReactFeatureFlags'); var ReactDOM; +var AsyncComponent = React.unstable_AsyncComponent; + describe('ReactDOMFiberAsync', () => { var container; @@ -25,16 +27,16 @@ describe('ReactDOMFiberAsync', () => { if (ReactDOMFeatureFlags.useFiber) { it('renders synchronously when feature flag is disabled', () => { - class Async extends React.Component { - static unstable_asyncUpdates = true; - render() { - return this.props.children; - } - } - ReactDOM.render(
Hi
, container); + ReactDOM.render( +
Hi
, + container, + ); expect(container.textContent).toEqual('Hi'); - ReactDOM.render(
Bye
, container); + ReactDOM.render( +
Bye
, + container, + ); expect(container.textContent).toEqual('Bye'); }); @@ -47,32 +49,25 @@ describe('ReactDOMFiberAsync', () => { ReactDOM = require('react-dom'); }); - it('unstable_asyncUpdates at the root makes the entire tree async', () => { - class Async extends React.Component { - static unstable_asyncUpdates = true; - render() { - return this.props.children; - } - } - ReactDOM.render(
Hi
, container); + it('AsyncComponent at the root makes the entire tree async', () => { + ReactDOM.render( +
Hi
, + container, + ); expect(container.textContent).toEqual(''); jest.runAllTimers(); expect(container.textContent).toEqual('Hi'); - ReactDOM.render(
Bye
, container); + ReactDOM.render( +
Bye
, + container, + ); expect(container.textContent).toEqual('Hi'); jest.runAllTimers(); expect(container.textContent).toEqual('Bye'); }); it('updates inside an async tree are async by default', () => { - class Async extends React.Component { - static unstable_asyncUpdates = true; - render() { - return this.props.children; - } - } - let instance; class Component extends React.Component { state = {step: 0}; @@ -82,7 +77,10 @@ describe('ReactDOMFiberAsync', () => { } } - ReactDOM.render(, container); + ReactDOM.render( + , + container, + ); expect(container.textContent).toEqual(''); jest.runAllTimers(); expect(container.textContent).toEqual('0'); @@ -93,11 +91,10 @@ describe('ReactDOMFiberAsync', () => { expect(container.textContent).toEqual('1'); }); - it('unstable_asyncUpdates creates an async subtree', () => { + it('AsyncComponent creates an async subtree', () => { let instance; - class Component extends React.Component { + class Component extends React.unstable_AsyncComponent { state = {step: 0}; - static unstable_asyncUpdates = true; render() { instance = this; return
{this.state.step}
; @@ -114,8 +111,7 @@ describe('ReactDOMFiberAsync', () => { }); it('updates inside an async subtree are async by default', () => { - class Component extends React.Component { - static unstable_asyncUpdates = true; + class Component extends React.unstable_AsyncComponent { render() { return ; } diff --git a/src/renderers/shared/fiber/ReactFiberClassComponent.js b/src/renderers/shared/fiber/ReactFiberClassComponent.js index 5da7250431182..a6cc6880020a5 100644 --- a/src/renderers/shared/fiber/ReactFiberClassComponent.js +++ b/src/renderers/shared/fiber/ReactFiberClassComponent.js @@ -388,7 +388,8 @@ module.exports = function( if ( ReactFeatureFlags.enableAsyncSubtreeAPI && workInProgress.type != null && - workInProgress.type.unstable_asyncUpdates === true + workInProgress.type.prototype != null && + workInProgress.type.prototype.unstable_isAsyncReactComponent === true ) { workInProgress.internalContextTag |= AsyncUpdates; } diff --git a/src/renderers/shared/fiber/ReactFiberReconciler.js b/src/renderers/shared/fiber/ReactFiberReconciler.js index d2f38655226dd..01ab6a1e913cd 100644 --- a/src/renderers/shared/fiber/ReactFiberReconciler.js +++ b/src/renderers/shared/fiber/ReactFiberReconciler.js @@ -225,7 +225,8 @@ module.exports = function( ReactFeatureFlags.enableAsyncSubtreeAPI && element != null && element.type != null && - (element.type: any).unstable_asyncUpdates === true; + element.type.prototype != null && + (element.type.prototype: any).unstable_isAsyncReactComponent === true; const priorityLevel = getPriorityContext(current, forceAsync); const nextState = {element}; callback = callback === undefined ? null : callback;