Skip to content

Commit d708ae8

Browse files
committed
Fix stale activeThread closure in beginLocalDispatch callback
Use a ref to always read the latest activeThread at invocation time, eliminating the risk of capturing a stale closure value when the component re-renders between useCallback memoization and actual call.
1 parent ee8790e commit d708ae8

File tree

1 file changed

+14
-14
lines changed

1 file changed

+14
-14
lines changed

apps/web/src/components/ChatView.tsx

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -341,20 +341,20 @@ function useLocalDispatchState(input: {
341341
}) {
342342
const [localDispatch, setLocalDispatch] = useState<LocalDispatchSnapshot | null>(null);
343343

344-
const beginLocalDispatch = useCallback(
345-
(options?: { preparingWorktree?: boolean }) => {
346-
const preparingWorktree = Boolean(options?.preparingWorktree);
347-
setLocalDispatch((current) => {
348-
if (current) {
349-
return current.preparingWorktree === preparingWorktree
350-
? current
351-
: { ...current, preparingWorktree };
352-
}
353-
return createLocalDispatchSnapshot(input.activeThread, options);
354-
});
355-
},
356-
[input.activeThread],
357-
);
344+
const activeThreadRef = useRef(input.activeThread);
345+
activeThreadRef.current = input.activeThread;
346+
347+
const beginLocalDispatch = useCallback((options?: { preparingWorktree?: boolean }) => {
348+
const preparingWorktree = Boolean(options?.preparingWorktree);
349+
setLocalDispatch((current) => {
350+
if (current) {
351+
return current.preparingWorktree === preparingWorktree
352+
? current
353+
: { ...current, preparingWorktree };
354+
}
355+
return createLocalDispatchSnapshot(activeThreadRef.current, options);
356+
});
357+
}, []);
358358

359359
const resetLocalDispatch = useCallback(() => {
360360
setLocalDispatch(null);

0 commit comments

Comments
 (0)