@samitouri / QOS-React / commits / c6b5622bff

Schedule side-effects to parents before their children

This is only for host nodes so that the DOM tree is fully updated by the time we've flushed. Classes will schedule their life-cycles *after* their children's side-effects.

Sebastian Markbage committed Jun 30, 2016 at 01:05 UTC c6b5622bffa92e358f12ac21d485aac67bb4f8d9
1 file changed +21 -13
src/renderers/shared/fiber/ReactFiberCompleteWork.js
+21 -13
@@ -17,8 +17,6 @@ import type { Fiber } from 'ReactFiber';
17 import type { HostConfig } from 'ReactFiberReconciler';
18 import type { ReifiedYield } from 'ReactReifiedYield';
19
20 -import type { TypeOfWork } from 'ReactTypeOfWork';
21 -
20 var ReactChildFiber = require('ReactChildFiber');
21 var ReactTypeOfWork = require('ReactTypeOfWork');
22 var {
@@ -37,8 +35,20 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
35 const createInstance = config.createInstance;
36 const prepareUpdate = config.prepareUpdate;
37
38 + function markForPreEffect(workInProgress : Fiber) {
39 + // Schedule a side-effect on this fiber, BEFORE the children's side-effects.
40 + if (workInProgress.firstEffect) {
41 + workInProgress.nextEffect = workInProgress.firstEffect;
42 + workInProgress.firstEffect = workInProgress;
43 + } else {
44 + workInProgress.firstEffect = workInProgress;
45 + workInProgress.lastEffect = workInProgress;
46 + }
47 + }
48 +
49 + /*
50 function markForPostEffect(workInProgress : Fiber) {
41 - // Schedule a side-effect on this fiber, after the children's side-effects.
51 + // Schedule a side-effect on this fiber, AFTER the children's side-effects.
52 if (workInProgress.lastEffect) {
53 workInProgress.lastEffect.nextEffect = workInProgress;
54 } else {
@@ -46,6 +56,7 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
56 }
57 workInProgress.lastEffect = workInProgress;
58 }
59 + */
60
61 function transferOutput(child : ?Fiber, returnFiber : Fiber) {
62 // If we have a single result, we just pass that through as the output to
@@ -124,13 +135,11 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
135 case HostContainer:
136 transferOutput(workInProgress.child, workInProgress);
137 // We don't know if a container has updated any children so we always
127 - // need to update it right now. We schedule this side-effect after
128 - // all the other side-effects in the subtree.
129 - // TODO: I just realized that this means that nodes are not in the DOM
130 - // document when componentDidMount/Update fires. I'll need to change
131 - // the order for host component effects to happen *before* their
132 - // children I think.
133 - markForPostEffect(workInProgress);
138 + // need to update it right now. We schedule this side-effect before
139 + // all the other side-effects in the subtree. We need to schedule it
140 + // before so that the entire tree is up-to-date before the life-cycles
141 + // are invoked.
142 + markForPreEffect(workInProgress);
143 return null;
144 case HostComponent:
145 console.log('/host component', workInProgress.type);
@@ -138,15 +147,14 @@ module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) {
147 const children = (child && !child.sibling) ? (child.output : ?Fiber | I) : child;
148 const newProps = workInProgress.pendingProps;
149 workInProgress.memoizedProps = newProps;
141 - if (workInProgress.alternate && workInProgress.stateNode != null) {
150 + if (current && workInProgress.stateNode != null) {
151 // If we have an alternate, that means this is an update and we need to
152 // schedule a side-effect to do the updates.
144 - const current = workInProgress.alternate;
153 const oldProps = current.memoizedProps;
154 const instance : I = workInProgress.stateNode;
155 if (prepareUpdate(instance, oldProps, newProps, children)) {
156 // This returns true if there was something to update.
149 - markForPostEffect(workInProgress);
157 + markForPreEffect(workInProgress);
158 }
159 workInProgress.output = instance;
160 } else {