mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Host environment side-effects
This creates a new API for processing side-effects on the host environment. During initial reconciliation host instances are created during the time sliced periods. During updates there is an opportunity for the host to prepare something on the instance during the time slicing, and to determine whether there were any changes. The could be thrown away. At the commit phase, these changes are finally committed to the host instance.
This commit is contained in:
@@ -20,20 +20,44 @@
|
||||
'use strict';
|
||||
|
||||
import type { Fiber } from 'ReactFiber';
|
||||
import type { HostChildren } from 'ReactFiberReconciler';
|
||||
|
||||
var ReactFiberReconciler = require('ReactFiberReconciler');
|
||||
|
||||
var scheduledHighPriCallback = null;
|
||||
var scheduledLowPriCallback = null;
|
||||
|
||||
type Props = { };
|
||||
type Instance = { id: number };
|
||||
|
||||
var instanceCounter = 0;
|
||||
|
||||
var NoopRenderer = ReactFiberReconciler({
|
||||
|
||||
createHostInstance() {
|
||||
|
||||
createInstance(type : string, props : Props, children : HostChildren<Instance>) : Instance {
|
||||
console.log('Create instance #' + instanceCounter);
|
||||
return {
|
||||
id: instanceCounter++
|
||||
};
|
||||
},
|
||||
|
||||
prepareUpdate(instance : Instance, oldProps : Props, newProps : Props, children : HostChildren<Instance>) : boolean {
|
||||
console.log('Prepare for update on #' + instance.id);
|
||||
return true;
|
||||
},
|
||||
|
||||
commitUpdate(instance : Instance, oldProps : Props, newProps : Props, children : HostChildren<Instance>) : void {
|
||||
console.log('Commit update on #' + instance.id);
|
||||
},
|
||||
|
||||
deleteInstance(instance : Instance) : void {
|
||||
console.log('Delete #' + instance.id);
|
||||
},
|
||||
|
||||
scheduleHighPriCallback(callback) {
|
||||
scheduledHighPriCallback = callback;
|
||||
},
|
||||
|
||||
scheduleLowPriCallback(callback) {
|
||||
scheduledLowPriCallback = callback;
|
||||
},
|
||||
|
||||
@@ -48,7 +48,7 @@ type Instance = {
|
||||
type: any,
|
||||
|
||||
// The local state associated with this fiber.
|
||||
stateNode: ?Object,
|
||||
stateNode: any,
|
||||
|
||||
// Conceptual aliases
|
||||
// parent : Instance -> return The parent happens to be the same as the
|
||||
|
||||
@@ -24,6 +24,8 @@ var {
|
||||
|
||||
module.exports = function<T, P, I>(config : HostConfig<T, P, I>) {
|
||||
|
||||
const commitUpdate = config.commitUpdate;
|
||||
|
||||
function commitWork(finishedWork : Fiber) : void {
|
||||
switch (finishedWork.tag) {
|
||||
case ClassComponent:
|
||||
@@ -33,7 +35,17 @@ module.exports = function<T, P, I>(config : HostConfig<T, P, I>) {
|
||||
// TODO: Attach children to root container.
|
||||
return;
|
||||
case HostComponent:
|
||||
console.log('commit updates to host component', finishedWork.type);
|
||||
if (finishedWork.stateNode == null || !finishedWork.alternate) {
|
||||
throw new Error('This should only be done during updates.');
|
||||
}
|
||||
const children = finishedWork.output;
|
||||
const newProps = finishedWork.memoizedProps;
|
||||
// If we have an alternate, that means this is an update and we need to
|
||||
// schedule a side-effect to do the updates.
|
||||
const current = finishedWork.alternate;
|
||||
const oldProps = current.memoizedProps;
|
||||
const instance : I = finishedWork.stateNode;
|
||||
commitUpdate(instance, oldProps, newProps, children);
|
||||
return;
|
||||
default:
|
||||
throw new Error('This unit of work tag should not have side-effects.');
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
import type { ReactCoroutine } from 'ReactCoroutine';
|
||||
import type { Fiber } from 'ReactFiber';
|
||||
import type { HostConfig } from 'ReactFiberReconciler';
|
||||
|
||||
import type { ReifiedYield } from 'ReactReifiedYield';
|
||||
|
||||
var ReactChildFiber = require('ReactChildFiber');
|
||||
@@ -33,6 +32,9 @@ var {
|
||||
|
||||
module.exports = function<T, P, I>(config : HostConfig<T, P, I>) {
|
||||
|
||||
const createInstance = config.createInstance;
|
||||
const prepareUpdate = config.prepareUpdate;
|
||||
|
||||
function markForPostEffect(workInProgress : Fiber) {
|
||||
// Schedule a side-effect on this fiber, after the children's side-effects.
|
||||
if (workInProgress.lastEffect) {
|
||||
@@ -120,13 +122,24 @@ module.exports = function<T, P, I>(config : HostConfig<T, P, I>) {
|
||||
case HostContainer:
|
||||
return null;
|
||||
case HostComponent:
|
||||
console.log('/host component', workInProgress.type);
|
||||
transferOutput(workInProgress.child, workInProgress);
|
||||
if (workInProgress.alternate) {
|
||||
const children = workInProgress.output;
|
||||
const newProps = workInProgress.memoizedProps;
|
||||
if (workInProgress.alternate && workInProgress.stateNode != null) {
|
||||
// If we have an alternate, that means this is an update and we need to
|
||||
// schedule a side-effect to do the updates.
|
||||
markForPostEffect(workInProgress);
|
||||
const current = workInProgress.alternate;
|
||||
const oldProps = current.memoizedProps;
|
||||
const instance : I = workInProgress.stateNode;
|
||||
if (prepareUpdate(instance, oldProps, newProps, children)) {
|
||||
// This returns true if there was something to update.
|
||||
markForPostEffect(workInProgress);
|
||||
}
|
||||
} else {
|
||||
const instance = createInstance(workInProgress.type, newProps, children);
|
||||
workInProgress.stateNode = instance;
|
||||
}
|
||||
console.log('/host component', workInProgress.type);
|
||||
return null;
|
||||
case CoroutineComponent:
|
||||
console.log('/coroutine component', workInProgress.pendingProps.handler.name);
|
||||
|
||||
@@ -22,18 +22,21 @@ var {
|
||||
LowPriority,
|
||||
} = require('ReactPriorityLevel');
|
||||
|
||||
type ReactHostElement<T, P> = {
|
||||
type: T,
|
||||
props: P
|
||||
};
|
||||
|
||||
type Deadline = {
|
||||
timeRemaining : () => number
|
||||
};
|
||||
|
||||
type HostChildNode<I> = { output: HostChildren<I>, sibling: ?HostChildNode<I> };
|
||||
|
||||
export type HostChildren<I> = null | void | I | HostChildNode<I>;
|
||||
|
||||
export type HostConfig<T, P, I> = {
|
||||
|
||||
createHostInstance(element : ReactHostElement<T, P>) : I,
|
||||
createInstance(type : T, props : P, children : HostChildren<I>) : I,
|
||||
prepareUpdate(instance : I, oldProps : P, newProps : P, children : HostChildren<I>) : bool,
|
||||
commitUpdate(instance : I, oldProps : P, newProps : P, children : HostChildren<I>) : void,
|
||||
deleteInstance(instance : I) : void,
|
||||
|
||||
scheduleHighPriCallback(callback : () => void) : void,
|
||||
scheduleLowPriCallback(callback : (deadline : Deadline) => void) : void
|
||||
|
||||
|
||||
Reference in New Issue
Block a user