Skip to content

feat(react19): migrate React 18 to 19 - #54

Merged
magicapple123 merged 2 commits into
mainfrom
feat/react-19
Oct 2, 2026
Merged

magicapple123 merged 2 commits into
mainfrom
feat/react-19

Conversation

@magicapple123

Copy link
Copy Markdown
Owner

Summary

react / react-dom ^18.3.1 → ^19.3.0,@types/react / @types/react-dom → ^19.3.0(版本逐字对齐)。同时删除 .github/dependabot.yml npm 段中 react/react-dom/@types/react/@types/react-dom 的 >=19 ignore 块(连同注释)——React 19 已正式落地。

Peer 全链核查(React 19 前置确认)

  • antd@6.6.5:react >= 18 ✓(且 v6 不再需要 react-19 patch)
  • react-router-dom@7.18.2:react >= 18 ✓
  • @testing-library/react@16.3.3:^18.0.0 || ^19.0.0 ✓(自带 act 兼容层)
  • 平台绑定条数与 main 一致:rolldown 15 / lightningcss 12 / fsevents 1

React 19 代码面(grep 审计)

  • forwardRef 仅 1 处(ResumePreview),v19 仍支持,本次不动结构
  • 无 react-dom/test-utils、findDOMNode、ReactDOM.render 用法;入口已是 createRoot
  • 类型面:React 19 的 useRef<T>(null) 返回 RefObject<T | null>,相关组件 ref prop 类型同步放宽(ResumePreviewCanvas / ResumePreviewToolbar / ResumeDetailPreview / AssistantMessageList / useAssistantStream 等)

测试惯例变化(断言不放松,均有证据)

  1. GenerateResumeModal(应用层竞态修复):watchResumeTask 注册时会"立刻拉一次",此前 mock 让任务注册瞬间即 completed,finish() 对"界面在看"的判定与弹窗完成收尾的 detach 存在竞态——React 19 的被动副作用落点使其从偶发变为确定性发生。修复:① mock 忠实于真实时序(首次 running、其后 completed);② "在看"声明改为只在弹窗真正关闭时 detach(完成收尾置空 taskId 不再误判"用户已走开")。"关闭弹窗后台继续 → 居中弹窗"的既有用例仍然通过。
  2. SettingsPage:antd 6 Password 受控 visible 经内部 effect 同步,React 19 下晚一拍落地,type 翻转断言改用 waitFor。
  3. QuestionBankPanel:antd 6 Button 的 loading 防抖窗口内点击会被内部吞掉(Button.handleClick 对 innerLoading 直接 return),收起前先等按钮退出 loading 态。

验证

  • npm run test:123 文件 / 801 用例全绿
  • npm run lint:0 error / 11 warning(存量基线持平)
  • npm run typecheck、format:check:通过
  • Rolldown 生产构建通过;dev server 冒烟通过

Upgrade react/react-dom ^18.3.1 -> ^19.3.0 and @types/react(+dom) to
^19.3.0 (versions aligned); drop the React>=19 ignore block from
.github/dependabot.yml now that React 19 has landed.

React 19 impact surface (grep-audited):
- forwardRef: 1 site (ResumePreview), still supported, kept as-is
- no react-dom/test-utils, findDOMNode or ReactDOM.render usage;
  entry already createRoot; RTL 16 provides the act compat layer
- RefObject/MutableRefObject prop types widened to React 19 semantics
  (useRef<T>(null) now yields RefObject<T | null>)

Test-convention updates (React 19 evidence, assertions not loosened):
- GenerateResumeModal: mock now returns running before completed, and
  the "watching" declaration now detaches only on modal close - React
  19's passive-effect scheduling made the pre-existing race between
  watchResumeTask's immediate tick and the completion-driven detach
  deterministic; closing the modal mid-generation still escalates to
  the centered modal (covered by the existing test)
- SettingsPage ApiKeyInput: antd 6 Password controlled visibility
  settles one tick late; type assertions await waitFor
- QuestionBankPanel: wait for the collapse button to leave antd's
  loading debounce window before clicking

Verified: vitest 801/801, eslint 0 errors (11 pre-existing warnings),
tsc clean, prettier clean, rolldown build ok, dev smoke ok, lockfile
platform bindings match main (rolldown 15 / lightningcss 12 / fsevents 1).
The navigation settings card fetches visibility on mount; while loading
the reset button is disabled and React swallows the click. On slower CI
runners the mock resolution lost the race. Assertions unchanged.
@magicapple123
magicapple123 merged commit 9e2b66b into main Oct 2, 2026
10 checks passed
@magicapple123
magicapple123 deleted the feat/react-19 branch October 2, 2026 09:38
magicapple123 added a commit that referenced this pull request Oct 2, 2026
antd 6 Form.useWatch notifies asynchronously and React 19 scheduling defers the re-render, so on slow CI machines the synchronous assertion read the fallback text before data injection rendered. Waits for the correct value to land (findByText) — assertion values unchanged. Fixes the post-#54 main CI Frontend flake.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant