Patch react-virtualized to fix react 18 scroll lag (#4370)

React 18 introduced automatic batching which tries to avoid unnecessary
re-rendering (https://react.dev/blog/2022/03/08/react-18-upgrade-guide#automatic-batching).
In some components based on react-virtualized (e.g. tag selector),
it leads to visible lagginess on scroll via keypress or
mouse wheel (not trackpad). This patch wraps setState of the scroll handler
of react-virtualized with ReactDOM.flushSync, which opts out
of automatic batching.

Fixes: #4368
This commit is contained in:
abaevbog 2024-07-10 22:18:25 -07:00 committed by GitHub
parent 657d5c4c42
commit a07117c938
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -46,6 +46,16 @@ async function babelWorker(ev) {
transformed = contents.replace('scrollDiv = document.createElement("div")', 'scrollDiv = document.createElementNS("http://www.w3.org/1999/xhtml", "div")')
.replace('document.body.appendChild(scrollDiv)', 'document.documentElement.appendChild(scrollDiv)')
.replace('document.body.removeChild(scrollDiv)', 'document.documentElement.removeChild(scrollDiv)');
// React 18: wrap setState in onScroll handler with ReactDOM.flushSync to avoid
// automatic batching https://react.dev/blog/2022/03/08/react-18-upgrade-guide#automatic-batching
// which causes less frequent re-rendering and lagginess on scroll of components such as tag selector
let onScrollSetStateChunkRegex = /(_this\.state\.isScrolling\s*\|\|\s*isScrollingChange\(!0\),\s*)(_this\.setState\s*\(\s*\{[^}]*\}\s*\))/;
if (!onScrollSetStateChunkRegex.test(transformed)) {
throw new Error(`"_this.state.isScrolling || isScrollingChange(!0), _this.setState({" not found in react-virtualized`);
}
transformed = transformed.replace(onScrollSetStateChunkRegex, (_, p1, p2) => {
return `${p1}ReactDOM.flushSync(() => ${p2.trim()})`;
});
}
// Patch single-file
else if (sourcefile === 'resource/SingleFile/lib/single-file.js') {