Skip to content

Commit 501e6ec

Browse files
committed
fix(RenderWindow): setState race conditions
It's possible for a queueRender to get batched with a setRenderRequested(false), resulting in the effect running once and caching a value of true for renderRequested. This prevents the effect from ever running again.
1 parent 9204b18 commit 501e6ec

File tree

1 file changed

+11
-11
lines changed

1 file changed

+11
-11
lines changed

src/core/RenderWindow.tsx

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
useEffect,
88
useImperativeHandle,
99
useMemo,
10-
useState,
10+
useRef,
1111
} from 'react';
1212
import { IRenderWindow } from '../types';
1313
import deletionRegistry from '../utils/DeletionRegistry';
@@ -60,16 +60,16 @@ export default forwardRef(function RenderWindow(props: Props, fwdRef) {
6060

6161
// --- rendering --- //
6262

63-
const [renderRequested, setRenderRequested] = useState(false);
64-
const queueRender = () => setRenderRequested(true);
65-
66-
useEffect(() => {
67-
if (renderRequested) {
68-
setRenderRequested(false);
69-
const renderWindow = getRenderWindow();
70-
renderWindow.render();
63+
const renderTimeoutRef = useRef<NodeJS.Timeout | null>(null);
64+
const queueRender = useCallback(() => {
65+
if (renderTimeoutRef.current == null) {
66+
renderTimeoutRef.current = setTimeout(() => {
67+
const renderWindow = getRenderWindow();
68+
renderWindow.render();
69+
renderTimeoutRef.current = null;
70+
});
7171
}
72-
}, [renderRequested, getRenderWindow]);
72+
}, [getRenderWindow]);
7373

7474
// --- resize --- //
7575

@@ -98,7 +98,7 @@ export default forwardRef(function RenderWindow(props: Props, fwdRef) {
9898
getInteractor,
9999
requestRender: queueRender,
100100
}),
101-
[getRenderWindow, getInteractor]
101+
[getRenderWindow, getInteractor, queueRender]
102102
);
103103

104104
useImperativeHandle(fwdRef, () => api);

0 commit comments

Comments
 (0)