diff --git a/Libraries/Experimental/Incremental.js b/Libraries/Experimental/Incremental.js deleted file mode 100644 index 11174c0c833294..00000000000000 --- a/Libraries/Experimental/Incremental.js +++ /dev/null @@ -1,198 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - * @flow - */ - -'use strict'; - -const InteractionManager = require('../Interaction/InteractionManager'); -const PropTypes = require('prop-types'); -const React = require('react'); - -const infoLog = require('../Utilities/infoLog'); - -const DEBUG = false; - -/** - * WARNING: EXPERIMENTAL. Breaking changes will probably happen a lot and will - * not be reliably announced. The whole thing might be deleted, who knows? Use - * at your own risk. - * - * React Native helps make apps smooth by doing all the heavy lifting off the - * main thread, in JavaScript. That works great a lot of the time, except that - * heavy operations like rendering may block the JS thread from responding - * quickly to events like taps, making the app feel sluggish. - * - * `` solves this by slicing up rendering into chunks that are - * spread across multiple event loops. Expensive components can be sliced up - * recursively by wrapping pieces of them and their descendants in - * `` components. `` can be used to make sure - * everything in the group is rendered recursively before calling `onDone` and - * moving on to another sibling group (e.g. render one row at a time, even if - * rendering the top level row component produces more `` chunks). - * `` is a type of `` that keeps it's - * children invisible and out of the layout tree until all rendering completes - * recursively. This means the group will be presented to the user as one unit, - * rather than pieces popping in sequentially. - * - * `` only affects initial render - `setState` and other render - * updates are unaffected. - * - * The chunks are rendered sequentially using the `InteractionManager` queue, - * which means that rendering will pause if it's interrupted by an interaction, - * such as an animation or gesture. - * - * Note there is some overhead, so you don't want to slice things up too much. - * A target of 100-200ms of total work per event loop on old/slow devices might - * be a reasonable place to start. - * - * Below is an example that will incrementally render all the parts of `Row` one - * first, then present them together, then repeat the process for `Row` two, and - * so on: - * - * render: function() { - * return ( - * - * {Array(10).fill().map((rowIdx) => ( - * - * - * {Array(20).fill().map((widgetIdx) => ( - * - * - * - * ))} - * - * - * ))} - * - * ); - * }; - * - * If SlowWidget takes 30ms to render, then without `Incremental`, this would - * block the JS thread for at least `10 * 20 * 30ms = 6000ms`, but with - * `Incremental` it will probably not block for more than 50-100ms at a time, - * allowing user interactions to take place which might even unmount this - * component, saving us from ever doing the remaining rendering work. - */ -export type Props = { - /** - * Called when all the descendants have finished rendering and mounting - * recursively. - */ - onDone?: () => void, - /** - * Tags instances and associated tasks for easier debugging. - */ - name: string, - children: React.Node, - ... -}; -type State = {doIncrementalRender: boolean, ...}; - -class Incremental extends React.Component { - props: Props; - state: State; - context: Context; - _incrementId: number; - _mounted: boolean; - _rendered: boolean; - - static defaultProps: {|name: string|} = { - name: '', - }; - - static contextTypes: - | any - | {| - incrementalGroup: React$PropType$Primitive, - incrementalGroupEnabled: React$PropType$Primitive, - |} = { - incrementalGroup: PropTypes.object, - incrementalGroupEnabled: PropTypes.bool, - }; - - constructor(props: Props, context: Context) { - super(props, context); - this._mounted = false; - this.state = { - doIncrementalRender: false, - }; - } - - getName(): string { - const ctx = this.context.incrementalGroup || {}; - return ctx.groupId + ':' + this._incrementId + '-' + this.props.name; - } - - UNSAFE_componentWillMount() { - const ctx = this.context.incrementalGroup; - if (!ctx) { - return; - } - this._incrementId = ++ctx.incrementalCount; - InteractionManager.runAfterInteractions({ - name: 'Incremental:' + this.getName(), - gen: () => - new Promise(resolve => { - if (!this._mounted || this._rendered) { - resolve(); - return; - } - DEBUG && infoLog('set doIncrementalRender for ' + this.getName()); - this.setState({doIncrementalRender: true}, resolve); - }), - }) - .then(() => { - DEBUG && infoLog('call onDone for ' + this.getName()); - this._mounted && this.props.onDone && this.props.onDone(); - }) - .catch(ex => { - ex.message = `Incremental render failed for ${this.getName()}: ${ - ex.message - }`; - throw ex; - }) - .done(); - } - - render(): React.Node { - if ( - this._rendered || // Make sure that once we render once, we stay rendered even if incrementalGroupEnabled gets flipped. - !this.context.incrementalGroupEnabled || - this.state.doIncrementalRender - ) { - DEBUG && infoLog('render ' + this.getName()); - this._rendered = true; - return this.props.children; - } - return null; - } - - componentDidMount() { - this._mounted = true; - if (!this.context.incrementalGroup) { - this.props.onDone && this.props.onDone(); - } - } - - componentWillUnmount() { - this._mounted = false; - } -} - -export type Context = { - incrementalGroupEnabled: boolean, - incrementalGroup: ?{ - groupId: string, - incrementalCount: number, - ... - }, - ... -}; - -module.exports = Incremental;