跳转至

系统性盲区 — 前端 React lifecycle 审查空白

来源

v0.10.45 第二轮独立 agent 在做"是否有系统性缺失"的元-评估时发现。

内容

本会话累计修了 14+ 真 bug(ISSUE-0023~0029),分布:

主题 数量
MV3 持久化 / SW 生命周期 5
拦截 / 调度 3
数据完整性(邮箱污染、writeChain) 2
UI 显示 / 文案 3
死代码清理 2

0 个针对: - useEffect cleanup 缺失 - setState on unmounted component - AbortController for in-flight fetch - Recoil/global state 误用 - React StrictMode 双 mount race

量化扫描

grep -rn "useEffect\|useState" src/sections/ src/components/ | wc -l334 处

其中: - 用 ahooks/useRequest 的部分 ✅ 有 unmount cancel 兜底 - useEffect(async () => { ... setState(...) }) —— 全部裸奔 ❌ - 仅 2 处用了 isMounted-style ref(都是 drag 相关,不是 fetch 保护)

为什么一直没查?

本会话审查模式偏 background / MV3 / 持久化。React 前端是另一套心智模型, 我的 review 路径没经过这里。

ISSUE-0029 S4 (local-data-view onMessage 无 cleanup) 是这类问题的第一个被修, 但 334 处 useEffect 中很可能还有同类。

紧迫度

低-中: - React 17/18 unmount race 大多数情况下表现为 console warning,不是用户可见 bug - 但长期可能导致内存泄漏 / 偶发奇怪状态 - 真要触发严重 bug 需要:快速 mount/unmount + setState race + 错误数据回流

修法(未来做)

Phase 1(扫描):写一个 scripts/scan-react-lifecycle.py 类似 scan:mv3: - 扫所有 useEffect(async () => { ... }) 但无 return cleanup - 扫所有 setState 后无 if (mounted) 守卫 - 给出基线 + diff 模式

Phase 2(系统性修):高频组件优先: - main-layout / data-view / local-data-view(已修一处) - task-view / settings-view - popup 相关组件

Phase 3(rule 化): - 写 docs/rules/react-lifecycle-checklist.md(类比 MV3持久化陷阱清单) - pre-commit hook 在 src/sections/ 或 src/components/ 改动时跑扫描

评估时机

  • 用户反馈"扩展用久了切 tab 卡 / 数据更新延迟" → 立即处理
  • 否则等下次 React 相关大改动时顺手做 Phase 1+2

元教训

审查盲区的发现需要元-评估视角。 我 4 轮自我 review + 第一轮独立 agent 都聚焦"找具体 bug",没人问"我们是不是一直没查某类风险"。 第二轮 agent 明确被 brief 这个角度才发现。

下次写 rule 时考虑加一条:"每 N 轮审查后跑一次元-评估,问:是否某类风险从未被检查过"。