setTimeout runs its callback codes much slower than without it
React batches renders that are queued up within an event callback, so all of your calls to setValue
in the click handler result in a single render once your handler finishes.
However, I do not believe React batches renders from within a setTimeout call. So it is rendering after each call to setValue
in your setTimeout handler.
See this issue: https://github.com/facebook/react/issues/14259
You should be able to make the setTimeout version faster by writing it like so:
const handleClick2 = () => {
setTimeout(() => ReactDOM.unstable_batchedUpdates(() => startSample()));
}
If you have a bunch of async ajax responses coming back and want to apply them after they all arrive, then you might have code like this:
const [a, setA] = useState();
const [b, setB] = useState();
const [c, setC] = useState();
const [d, setD] = useState();
useEffect(() => {
(async () => {
const a = await fetchA();
const b = await fetchB();
const c = await fetchC();
const d = await fetchD();
// wrap all of the state updates in batchUpdates
// so that we only get one render instead of 4
ReactDOM.unstable_batchUpdates(() => {
setA(a);
setB(b);
setC(c);
setD(d);
});
})()
}), []);
React currently will batch state updates if they're triggered from within a React-based event, like a button click or input change. It will not batch updates if they're triggered outside of a React event handler, like a setTimeout().
Consider the following
const startSample = () => {
const startTimeStamp = new Date().valueOf();
const arr = []
for (let i = 0; i < 5000; i++) {
arr.push(i)
// console.log(`test-${i}`);
}
setValue(arr)
const endTimeStamp = new Date().valueOf();
setTime(`${endTimeStamp - startTimeStamp}ms`);
};
Now both times are about the same right? As pointed out by Brandon React doesn't seem to wait all udpates finishes before triggering a new render, resulting in five thousand renders instead of just one. So use an accumulator to perform the iterations and set the state just once