Skip to content

fix(cowork): CopyButton 组件卸载后定时器未清理导致内存泄漏 - #1478

Closed
linlihua wants to merge 1 commit into
netease-youdao:mainfrom
linlihua:fix/copy-button-timer-leak
Closed

fix(cowork): CopyButton 组件卸载后定时器未清理导致内存泄漏#1478
linlihua wants to merge 1 commit into
netease-youdao:mainfrom
linlihua:fix/copy-button-timer-leak

Conversation

@linlihua

@linlihua linlihua commented Apr 4, 2026

Copy link
Copy Markdown

问题背景

关联 Issue:#886
对话详情页的复制按钮(CopyButton)点击后使用裸 setTimeout 在 2 秒后
重置复制状态。当组件在定时器触发前卸载(如用户快速切换会话、消息列表
重渲染),回调仍会执行 setCopied(false),产生 React「更新已卸载组件」
警告及潜在内存泄漏。

根本原因

// 修复前
const handleCopy = async () => {
  await navigator.clipboard.writeText(content);
  setCopied(true);
  setTimeout(() => setCopied(false), 2000);  // ← 裸 setTimeout,无清理
};
setTimeout 返回的 timer ID 没有被保存,组件也没有在卸载时
清理该定时器。在对话流式输出期间,消息列表频繁重渲染,
CopyButton 可能被反复挂载/卸载,泄漏的定时器会不断累积。
修复方案
采用同仓库 MarkdownContent.tsx 中已验证的正确模式:
// 修复后
const copyTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
useEffect(() => {
  return () => {
    if (copyTimerRef.current) clearTimeout(copyTimerRef.current);
  };
}, []);
const handleCopy = async () => {
  await navigator.clipboard.writeText(content);
  setCopied(true);
  if (copyTimerRef.current) clearTimeout(copyTimerRef.current);
  copyTimerRef.current = setTimeout(() => setCopied(false), 2000);
};
-  useRef 持有 timer ID
- useEffect cleanup  clearTimeout 确保卸载时清理
- 连续点击时先清除上一个 timer 再创建新的,避免多个并发定时器
变更文件
- src/renderer/components/cowork/CoworkSessionDetail.tsx  CopyButton
  组件 setTimeout 替换为 useRef + useEffect cleanup
测试结果
Test Files  19 passed (22)
Tests      225 passed (225)

The CopyButton component used a bare setTimeout to reset the copied
state after 2 seconds. If the component unmounted before the timer
fired (e.g. user navigates away or the message list re-renders), the
callback tried to call setCopied on an unmounted component, producing
a React warning and a minor memory leak.

Fix: store the timer ID in a useRef and clear it in a useEffect
cleanup function on unmount, following the same pattern already used
in MarkdownContent.tsx. Also clear any pending timer before starting
a new one on rapid re-clicks.

Closes netease-youdao#886
@github-actions

Copy link
Copy Markdown

This pull request has been inactive for 30 days. It will be automatically closed in 14 days unless there is new activity.

If you're still working on this, please leave a comment or push new commits to keep it open. Thank you!

@github-actions

Copy link
Copy Markdown

This pull request was automatically closed due to inactivity. Feel free to reopen it if you'd like to continue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant