From 0d182853e3562a77826aca95c514a91f9d3bc5bf Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Mon, 6 Dec 2021 12:21:46 -0500 Subject: [PATCH 1/2] Fire useEffect in reverse component depth order This changes the ordering of useEffect callbacks so that they fire roughly in order of reverse component depth. Callbacks will still fire in-order for multiple useEffect()'s within a single component, but the callbacks for a child component will fire before those of a parent. --- hooks/src/index.js | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/hooks/src/index.js b/hooks/src/index.js index ca87285ce4..93812b1197 100644 --- a/hooks/src/index.js +++ b/hooks/src/index.js @@ -288,19 +288,18 @@ export function useErrorBoundary(cb) { * After paint effects consumer. */ function flushAfterPaintEffects() { - afterPaintEffects.forEach(component => { - if (component._parentDom) { - try { - component.__hooks._pendingEffects.forEach(invokeCleanup); - component.__hooks._pendingEffects.forEach(invokeEffect); - component.__hooks._pendingEffects = []; - } catch (e) { - component.__hooks._pendingEffects = []; - options._catchError(e, component._vnode); - } + let component; + while (component = afterPaintEffects.pop()) { + if (!component._parentDom) continue; + try { + component.__hooks._pendingEffects.forEach(invokeCleanup); + component.__hooks._pendingEffects.forEach(invokeEffect); + component.__hooks._pendingEffects = []; + } catch (e) { + component.__hooks._pendingEffects = []; + options._catchError(e, component._vnode); } - }); - afterPaintEffects = []; + } } let HAS_RAF = typeof requestAnimationFrame == 'function'; From 6e58ab518f56563dfb08199b5d628e5f0d7e20e4 Mon Sep 17 00:00:00 2001 From: Jason Miller Date: Tue, 7 Dec 2021 15:04:30 -0500 Subject: [PATCH 2/2] Sort useEffect callbacks by tree depth --- hooks/src/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hooks/src/index.js b/hooks/src/index.js index 93812b1197..ec19748d18 100644 --- a/hooks/src/index.js +++ b/hooks/src/index.js @@ -289,6 +289,8 @@ export function useErrorBoundary(cb) { */ function flushAfterPaintEffects() { let component; + // sort the queue by depth (outermost to innermost) + afterPaintEffects.sort((a, b) => a._vnode._depth - b._vnode._depth); while (component = afterPaintEffects.pop()) { if (!component._parentDom) continue; try {