fix(web): stop writing choice-card visibility into a ref during render
Independent Staging Quality Gate / validate (push) Successful in 11m56s
Independent Staging Quality Gate / publish (push) Successful in 17m31s

Staging lint failed on react-hooks/refs after the jump overlay fix.
Keep the latest card-open flag in the existing layout effect so ESLint
passes and the overlay still stays off the choice card.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-08-25 21:26:26 +08:00
parent f5e73ef326
commit 69ebbb9917
3 changed files with 22 additions and 1 deletions
+16
View File
@@ -5579,6 +5579,22 @@
- 复发自:BUG-375(区分卡已落到剩余分钟,但题型仍是存在性,选题顺序仍写死)
- 修复版本:待发布
## BUG-383 | 点选卡开关在 render 里写 refstaging ESLint 失败
- 状态:resolved
- 首次发现:2026-08-25
- 最近更新:2026-08-25
- 影响面:Gitea `backend-quality-gate``npm run lint --prefix frontend``frontend/src/components/rectification-agentic-chat.tsx`
- 用户现象:向 `staging` 推送 `f5e73ef3` 后 quality gate run `2073` 失败。`validate` job `5170` 前端测试 2042/2042 通过,随后 lint `✖ 17 problems (1 error, 16 warnings)``publish` job `5171``needs: validate` 跳过。
- 触发条件:含 BUG-381「回到最新」避让点选卡的提交进入完整 `xiaoxin` runner 的 frontend lint。
- 根因:`react-hooks/refs` 禁止在 render 期间更新 `ref.current`。BUG-381 用 `choiceCardsOpen.current = showChoiceCards` 给滚动回调最新点选卡开关,写在 render 里。父提交 `7a4360d8` 的 run `2072` 已因同一行失败。
- 修复:把 ref 写入现有 `useLayoutEffect`,再调用 `updateFollowState`。不改 Skill `10.0.11`
- 验证:`npx eslint src/components/rectification-agentic-chat.tsx``frontend/tests/rectification-agentic-entry.test.ts`
- 防复发:点选卡可见状态不得在 render 里写 `ref.current`;源码合同锁定该赋值只出现在 layout effect。
- 相关记录:BUG-326、BUG-381
- 复发自:BUG-326(窄屏盘面 `onCloseRef.current = onClose` 同样在 render 里写 ref
- 修复版本:待发布
## BUG-379 | 生时纠正已记入学后仍编造高考年并再问入学
- 状态:resolved
@@ -983,8 +983,8 @@ export function RectificationAgenticChat(props: RectificationAgenticChatProps) {
&& !readonly
&& regeneratingMessageKey === null,
);
choiceCardsOpen.current = showChoiceCards;
useLayoutEffect(() => {
choiceCardsOpen.current = showChoiceCards;
updateFollowState();
}, [showChoiceCards, updateFollowState]);
const showSelectionCards = Boolean(
@@ -278,6 +278,11 @@ test("Agentic rectification follows the conversation tail only while the reader
assert.match(chat, /top: viewport\.scrollHeight/);
assert.match(chat, /shouldShowJumpToLatest/);
assert.match(chat, /choiceCardsOpen/);
assert.match(
chat,
/useLayoutEffect\(\(\) => \{\s*choiceCardsOpen\.current = showChoiceCards;\s*updateFollowState\(\);\s*\}, \[showChoiceCards, updateFollowState\]\)/,
);
assert.doesNotMatch(chat, /choiceCardsOpen\.current = showChoiceCards;\s*useLayoutEffect/);
assert.match(chat, /updateFollowState/);
assert.match(chat, /\}, \[busy, candidateResult, choiceCard, error, messages, savedTime, followLatestContent\]\);/);
assert.match(styles, /\.rectification-jump-latest \{[\s\S]*justify-content: flex-end/);