The TypeScript check passed with no errors. The debounce pattern from VirtualizedProcessLogs.tsx has been successfully rolled out to ConversationList.tsx. (#1909)

## Summary

Added 100ms debounce to `ConversationList.tsx` matching the pattern in `VirtualizedProcessLogs.tsx`:

1. **Added refs** (lines 94-99): `pendingUpdateRef` to store pending updates and `debounceTimeoutRef` to track the timeout
2. **Modified `onEntriesUpdated`** (lines 115-149): Now stores updates in the ref and debounces state updates with a 100ms delay
3. **Added cleanup effect** (lines 107-113): Clears any pending timeout on unmount to prevent memory leaks
This commit is contained in:
Louis Knight-Webb
2026-01-10 11:18:44 +00:00
committed by GitHub
parent a92c35d42e
commit e2fad0e10c

View File

@@ -91,6 +91,12 @@ export function ConversationList({ attempt, task }: ConversationListProps) {
useState<DataWithScrollModifier<PatchTypeWithKey> | null>(null);
const [loading, setLoading] = useState(true);
const { setEntries, reset } = useEntries();
const pendingUpdateRef = useRef<{
entries: PatchTypeWithKey[];
addType: AddEntryType;
loading: boolean;
} | null>(null);
const debounceTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
useEffect(() => {
setLoading(true);
@@ -98,25 +104,48 @@ export function ConversationList({ attempt, task }: ConversationListProps) {
reset();
}, [attempt.id, reset]);
useEffect(() => {
return () => {
if (debounceTimeoutRef.current) {
clearTimeout(debounceTimeoutRef.current);
}
};
}, []);
const onEntriesUpdated = (
newEntries: PatchTypeWithKey[],
addType: AddEntryType,
newLoading: boolean
) => {
pendingUpdateRef.current = {
entries: newEntries,
addType,
loading: newLoading,
};
if (debounceTimeoutRef.current) {
clearTimeout(debounceTimeoutRef.current);
}
debounceTimeoutRef.current = setTimeout(() => {
const pending = pendingUpdateRef.current;
if (!pending) return;
let scrollModifier: ScrollModifier = InitialDataScrollModifier;
if (addType === 'plan' && !loading) {
if (pending.addType === 'plan' && !loading) {
scrollModifier = ScrollToTopOfLastItem;
} else if (addType === 'running' && !loading) {
} else if (pending.addType === 'running' && !loading) {
scrollModifier = AutoScrollToBottom;
}
setChannelData({ data: newEntries, scrollModifier });
setEntries(newEntries);
setChannelData({ data: pending.entries, scrollModifier });
setEntries(pending.entries);
if (loading) {
setLoading(newLoading);
setLoading(pending.loading);
}
}, 100);
};
useConversationHistory({ attempt, onEntriesUpdated });