Skip to content

Commit

Permalink
Improve nested effect rerenders in act (-49 B)
Browse files Browse the repository at this point in the history
Currently `act` relies on a new internal option (`options.hooks`) to detect if a rerender queued up more effects to run. This PR removes `options.hooks` and instead detects if there are new effects to run by continuing to flush and rerender as long as `options.requestAnimationFrame` is invoked.
  • Loading branch information
andrewiggins committed Apr 17, 2019
1 parent 4bcdb86 commit 1cae60b
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 14 deletions.
5 changes: 0 additions & 5 deletions hooks/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ export function useEffect(callback, args) {
state._args = args;

currentComponent.__hooks._pendingEffects.push(state);
if (Array.isArray(options.effects)) options.effects.push(state);
afterPaint(currentComponent);
}
}
Expand All @@ -126,7 +125,6 @@ export function useLayoutEffect(callback, args) {
if (argsChanged(state._args, args)) {
state._value = callback;
state._args = args;
if (Array.isArray(options.effects)) options.effects.push(state);
currentComponent.__hooks._pendingLayoutEffects.push(state);
}
}
Expand Down Expand Up @@ -221,9 +219,6 @@ if (typeof window !== 'undefined') {
function handleEffects(effects) {
effects.forEach(invokeCleanup);
effects.forEach(invokeEffect);
if (options.effects) {
effects.forEach(hook => options.effects = options.effects.filter(h => h!==hook));
}
return [];
}

Expand Down
26 changes: 17 additions & 9 deletions test-utils/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,32 @@ export function setupRerender() {
return () => options.__test__drainQueue && options.__test__drainQueue();
}

/**
* Run a test function, and flush all effects and rerenders after invoking it
* @param {() => void} cb The function under test
*/
export function act(cb) {
options.effects = [];
const previousRequestAnimationFrame = options.requestAnimationFrame;
const rerender = setupRerender();
let flush;

/** @type {() => void} */
let flush, toFlush;

// Override requestAnimationFrame so we can flush pending hooks.
options.requestAnimationFrame = (fc) => flush = fc;

// Execute the callback we were passed.
cb();
rerender();
if (flush) {
// State COULD be built up flush it.
while (options.effects.length > 0) {
flush();
rerender();
}

while (flush) {
toFlush = flush;
flush = null;

toFlush();
rerender();
}
options.effects = undefined;

options.requestAnimationFrame = previousRequestAnimationFrame;
}

Expand Down

0 comments on commit 1cae60b

Please sign in to comment.