Files
react/packages/react-devtools-shell/src/app/InteractionTracing/index.js
T
Brian Vaughn b38ac13f94 DevTools: Add post-commit hook (#21183)
I recently added UI for the Profiler's commit and post-commit durations to the DevTools, but I made two pretty silly oversights:

    1. I used the commit hook (called after mutation+layout effects) to read both the layout and passive effect durations. This is silly because passive effects may not have flushed yet git at this point.
    2. I didn't reset the values on the HostRoot node, so they accumulated with each commit.

    This commitR addresses both issues:

    1. First it adds a new DevTools hook, onPostCommitRoot*, to be called after passive effects get flushed. This gives DevTools the opportunity to read passive effect durations (if the build of React being profiled supports it).
    2. Second the work loop resets these durations (on the HostRoot) after calling the post-commit hook so address the accumulation problem.
    I've also added a unit test to guard against this regressing in the future.

    * Doing this in flushPassiveEffectsImpl seemed simplest, since there are so many places we flush passive effects. Is there any potential problem with this though?
2021-04-08 22:04:51 -04:00

104 lines
2.2 KiB
JavaScript

/**
* 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.
*
* @flow
*/
import * as React from 'react';
import {
Fragment,
useCallback,
useLayoutEffect,
useEffect,
useState,
} from 'react';
import {unstable_batchedUpdates as batchedUpdates} from 'react-dom';
import {
unstable_trace as trace,
unstable_wrap as wrap,
} from 'scheduler/tracing';
function sleep(ms) {
const start = performance.now();
let now;
do {
now = performance.now();
} while (now - ms < start);
}
export default function InteractionTracing() {
const [count, setCount] = useState(0);
const [shouldCascade, setShouldCascade] = useState(false);
const handleUpdate = useCallback(() => {
trace('count', performance.now(), () => {
setTimeout(
wrap(() => {
setCount(count + 1);
}),
count * 100,
);
});
}, [count]);
const handleCascadingUpdate = useCallback(() => {
trace('cascade', performance.now(), () => {
setTimeout(
wrap(() => {
batchedUpdates(() => {
setCount(count + 1);
setShouldCascade(true);
});
}),
count * 100,
);
});
}, [count]);
const handleMultiple = useCallback(() => {
trace('first', performance.now(), () => {
trace('second', performance.now(), () => {
setTimeout(
wrap(() => {
setCount(count + 1);
}),
count * 100,
);
});
});
}, [count]);
useEffect(() => {
if (shouldCascade) {
setTimeout(
wrap(() => {
setShouldCascade(false);
}),
count * 100,
);
}
}, [count, shouldCascade]);
useLayoutEffect(() => {
sleep(150);
});
useEffect(() => {
sleep(300);
});
return (
<Fragment>
<h1>Interaction Tracing</h1>
<button onClick={handleUpdate}>Update ({count})</button>
<button onClick={handleCascadingUpdate}>
Cascading Update ({count}, {shouldCascade ? 'true' : 'false'})
</button>
<button onClick={handleMultiple}>Multiple</button>
</Fragment>
);
}