
awesome-copilot 的 react18-upgrade 插件面向 React 16/17 类组件代码库的 React 18.3.1 企业级迁移工具链【免费下载链接】awesome-copilotCommunity-contributed instructions, agents, skills, and configurations to help you make the most of GitHub Copilot.项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-copilot导读react18-upgrade 插件 是 awesome-copilot 社区仓库中一套专门面向「类组件class-component重度代码库」的 React 迁移工具链它把 React 16/17 → React 18.3.1 的升级拆解为六个专职 Agent 与七个配套 Skill覆盖审计、依赖升级、生命周期迁移、自动批处理修复与测试改造五个阶段。阅读本文后你将掌握该插件的安装方式、五阶段流水线的工作原理、每个 Agent 的职责边界与门禁Gate判定标准以及底层 Skill 提供的 grep 扫描命令、依赖兼容矩阵与代码迁移范式从而能够在自己或团队的类组件项目中复现这套可中断、可恢复、以零告警为终点的迁移流程。插件概览为什么需要一套「企业级」React 迁移工具React 官方为类组件开发者提供的是UNSAFE_前缀逃生通道但react18-upgrade插件明确拒绝这条捷径。插件 README 开篇即定义了自己的使命migrating React 16/17 class-component codebases to React 18.3.1且目标是「零容忍未完成迁移」——不是简单地把componentWillMount改名为UNSAFE_componentWillMount而是执行真正的语义迁移产出「零弃用告警」的代码基线。从 plugin.json 可以看到该插件由 6 个 Agentreact18-auditor、react18-batching-fixer、react18-class-surgeon、react18-commander、react18-dep-surgeon、react18-test-guardian与 7 个 Skillreact-audit-grep-patterns、react18-batching-patterns、react18-dep-compatibility、react18-enzyme-to-rtl、react18-legacy-context、react18-lifecycle-patterns、react18-string-refs组成版本号 1.0.0关键词覆盖react18、migration、upgrade、class-components、lifecycle、batching由 Awesome Copilot Community 维护采用 MIT 协议。这套设计背后的核心判断是React 16/17 时代积累的类组件模式从未向开发者报警告——它们静默工作了多年只有在升级到 React 18.3.1 时才会被显式警告全部暴露。因此迁移不是「升级依赖」这一件事而是一条需要审计、手术、修复、验证多角色协作的流水线。安装与使用插件通过 Copilot 的插件系统安装命令如下copilot plugin install react18-upgradeawesome-copilot安装完成后最快上手方式是在 Copilot 中直接发起Ask: Start implementing React 18 migration for my class-component codebasereact18-commander会接管整个流程引导你依次完成以下五个阶段Audit→ 识别全部破坏性变更Deps→ 升级到 react18.3.1 兼容库Class Surgery→ 迁移生命周期方法与 APIBatching Fixes→ 修复自动批处理回归Tests→ 迁移测试套件并跑到全绿五阶段流水线react18-commander 的编排机制为什么选中 18.3.1 作为锚点版本这是整个插件设计的第一性原则README 与 react18-commander.agent.md 反复强调React 18.3.1 was released to surfaceexplicit warningsfor every API that React 19 will remove. A clean 18.3.1 run with zero warnings is the direct prerequisite for the React 19 migration.也就是说18.3.1 是「警示板」版本——它会为所有 React 19 将要删除的 API 发出显式弃用警告。一次零告警的 18.3.1 构建就是后续 React 19 迁移管弦乐队的直接前置条件。因此依赖手术阶段要求精确锁定react18.3.1/react-dom18.3.1而不是^18或latest。基于 Memory 的可恢复状态机react18-commander使用vscode/memory工具实现可中断、可恢复的流水线。每次启动先读取迁移状态每个门禁通过后写入状态#tool:memory read repository react18-migration-state #tool:memory write repository react18-migration-state [state JSON]状态 JSON 的结构如下{ phase: audit|deps|class-surgery|batching|tests|done, reactVersion: null, auditComplete: false, depsComplete: false, classSurgeryComplete: false, batchingComplete: false, testsComplete: false, consoleWarnings: 0, testFailures: 0, lastRun: ISO timestamp }指挥官的开机序列Boot Sequence为读取内存报告已完成阶段 → 检测当前版本 → 若已在 18.3.x 则跳过依赖阶段直接从 class-surgery 开始若在 16.x/17.x 则从 audit 开始。版本检测命令node -e console.log(require(./node_modules/react/package.json).version) 2/dev/null || grep react package.json | head -3每个阶段都有明确的门禁Gate例如 Phase 1 的门禁是「.github/react18-audit.md存在且分类填充完整」Phase 5 的门禁是「npm test0 failures / 0 errors」全部通过后才写内存推进到下一阶段。最终验证门禁Phase 5 之后指挥官亲自执行最终验证echo BUILD npm run build 21 | tail -20 echo TESTS npm test -- --watchAllfalse --passWithNoTests --forceExit 21 | grep -E Tests:|Test Suites:|FAIL echo REACT 18.3.1 DEPRECATION WARNINGS # Start app in test mode and check for console warnings npm run build 21 | grep -i warning\|deprecated\|UNSAFE_ | head -20COMPLETE ✅ 仅当同时满足构建退出码 0、测试 0 失败、构建输出中无 React 弃用告警。若仍有弃用告警——这些是 React 19 的「地雷」——指挥官会带着具体告警信息重新召唤react18-class-surgeon。六个专职 Agent 深度拆解1. react18-auditor只读不写的深度扫描者react18-auditor.agent.md 的座右铭是Read everything. Fix nothing.它的唯一产出是.github/react18-audit.md审计报告。审计分 10 个阶段PHASE 0 代码库画像统计 JS/JSX 文件总数、类组件 vs 函数组件比例决定工作量PHASE 1 不安全生命周期扫描componentWillMount/componentWillReceiveProps/componentWillUpdate需排除UNSAFE_前缀与测试文件PHASE 2 自动批处理漏洞定位 async 方法中的多重 setState、setTimeout/Promise 内的 setState、原生事件处理器中的 setState、await 后读取this.state的条件 setStatePHASE 3 旧版 Context扫描childContextTypes提供方、contextTypes消费方、getChildContext、this.contextPHASE 4 字符串 refs扫描ref...与this.refs.PHASE 5 findDOMNode扫描findDOMNode/ReactDOM.findDOMNodePHASE 6 Root API扫描ReactDOM.render/ReactDOM.hydrate/unmountComponentAtNodePHASE 7 事件委托变更扫描document.addEventListenerReact 17 起事件委托从 document 移到根容器PHASE 8 StrictMode 状态确认项目是否曾启用 StrictMode决定 UNSAFE_ 前缀残留量PHASE 9 依赖兼容性列出 React 生态依赖的当前版本并检查 peer 冲突PHASE 10 测试文件审计定位遗留 render 模式、手工批处理假设、Enzyme 使用情况审计报告按「 静默运行时破坏者自动批处理、Enzyme/ 18.3.1 告警不安全生命周期、旧版 Root API/ 18.3.1 告警且 React 19 移除旧版 Context、字符串 refs、findDOMNode/ 事件委托审计 / 依赖问题」分级组织最后输出按序迁移计划15 步与全部受影响文件清单。所有 grep 模式沉淀在 react-audit-grep-patterns Skill 中其中定义了基础命令约定SRC_FLAGS--include*.js --include*.jsx EXCLUDE_TESTSgrep -v \.test\.\|\.spec\.\|__tests__2. react18-dep-surgeon精确锁定的依赖手术师react18-dep-surgeon.agent.md 的目标不是「装最新版」而是精确锁定react18.3.1。它按 9 步执行其中最关键的两个判断Enzyme 是硬阻断BLOCKEREnzyme 没有 React 18 适配器。若在package.json中发现 Enzyme依赖手术师不得继续升级 React而是回报指挥官BLOCKED - Enzyme detected必须先由 test-guardian 将所有 Enzyme 测试重写为 RTL。react-router v5 是单独迁移战役v5 → v6 是完全不同的 APIhooks、嵌套路由均改变。若发现 v5指挥官须决策现在迁移路由还是用react-router-dom^5.3.4的 React 18 peer 兼容方案 --legacy-peer-deps另开一次路由迁移冲刺。核心升级命令# STEP 1 - 精确锁定不是 ^18 或 latest npm install --save-exact react18.3.1 react-dom18.3.1 # STEP 2 - RTL v14v13 及以下内部使用 ReactDOM.render在并发模式下不可用 npm install --save-dev \ testing-library/react^14.0.0 \ testing-library/jest-dom^6.0.0 \ testing-library/user-event^14.0.0 # STEP 3 - Apollo 3.8useSyncExternalStore npm install apollo/clientlatest graphqllatest # STEP 4 - Emotion 11.10 npm install emotion/reactlatest emotion/styledlatestpeer 冲突解决规则很严格绝不使用--force--legacy-peer-deps仅在包没有 React 18 版本且仍在积极维护时允许且必须在 package.json 或 MIGRATION.md 中记录原因。GO/NO-GO 判定react18.3.1✅ 精确、react-dom18.3.1✅ 精确、testing-library/react14.x✅、npm ls0 peer 错误 ✅、Enzyme 不存在或已重写✅全部满足才返回 GO。3. react18-class-surgeon生命周期与 API 语义迁移专家react18-class-surgeon.agent.md 负责 7 类迁移核心原则是做真正的语义迁移绝不用UNSAFE_前缀当永久修复那是技术债React 19 里前缀与否都会被删除。它逐文件处理、逐文件写入 memory 检查点、绝不触碰测试文件。MIGRATION 1 - componentWillMount三种正确去向Case A初始化状态→ 移入 constructor// Before componentWillMount() { this.setState({ items: [], loading: false }); } // After constructor(props) { super(props); this.state { items: [], loading: false }; }Case B副作用fetch、订阅、DOM 设置→ 移入componentDidMountCase C从 props 推导初始状态→ constructor 中用 propsconstructor(props) { super(props); this.state { value: props.initialValue * 2 }; }MIGRATION 2 - componentWillReceiveProps两条正确路径关键决策规则在 react18-lifecycle-patterns 中固化为速查表方法做了什么正确迁移异步副作用fetch、取消请求componentDidUpdate基于 prevProps 比较纯状态推导无副作用static getDerivedStateFromPropsgetDerivedStateFromProps有一个陷阱它在每次渲染时都会触发不只是 props 变化时因此必须在 state 中记录上一个值以避免无限推导循环static getDerivedStateFromProps(props, state) { if (props.items ! state.prevItems) { return { sortedItems: sortItems(props.items), prevItems: props.items, }; } return null; } // 同时需在 constructor state 中加入 prevItems: props.itemsMIGRATION 3 - componentWillUpdategetSnapshotBeforeUpdate 配对读取 DOM 的场景滚动位置保持用getSnapshotBeforeUpdate捕获快照、componentDidUpdate应用getSnapshotBeforeUpdate(prevProps, prevState) { if (prevProps.listLength this.props.listLength) { return this.listRef.current.scrollHeight; } return null; } componentDidUpdate(prevProps, prevState, snapshot) { if (snapshot ! null) { this.listRef.current.scrollTop this.listRef.current.scrollHeight - snapshot; } }MIGRATION 4 - 旧版 Context → createContextreact18-legacy-context 明确指出这永远是跨文件迁移必须按固定顺序执行——找提供方 → 找全部消费方 → 创建 context 文件 → 更新提供方 → 更新每个消费方 → 验证。漏掉任何一个消费方都会导致运行时读取到错误 context 或undefined。提供方childContextTypesgetChildContext改为// ThemeContext.js export const ThemeContext React.createContext({ theme: light, toggleTheme: () {} }); class ThemeProvider extends React.Component { render() { return ( ThemeContext value{{ theme: this.state.theme, toggleTheme: this.toggleTheme }} {this.props.children} /ThemeContext ); } }类组件消费方用单数static contextType注意是contextType不是contextTypes函数组件消费方用useContext。MIGRATION 5 - 字符串 refs → React.createRef()constructor(props) { super(props); this.myInputRef React.createRef(); } render() { return input ref{this.myInputRef} /; } handleFocus() { this.myInputRef.current.focus(); }MIGRATION 6 - findDOMNode → 直接 ref为组件挂containerRef React.createRef()把 ref 绑到根 DOM 节点上直接this.containerRef.current。MIGRATION 7 - ReactDOM.render → createRoot这是解锁自动批处理与并发特性的关键迁移通常只涉及入口文件// Before ReactDOM.render(App /, document.getElementById(root)); // After import { createRoot } from react-dom/client; const root createRoot(document.getElementById(root)); root.render(App /);每类迁移后 class-surgeon 会用 grep 自检计数归零例如grep -rn componentWillMount\b\|componentWillReceiveProps\b\|componentWillUpdate\b src/ | grep -v UNSAFE_\|\.test\. | wc -l结果必须为 0。4. react18-batching-fixer自动批处理回归专家自动批处理被指挥官明确称为React 18 头号静默运行时破坏者#1 silent runtime breaker也是整个迁移中最阴险的一项——它不报错、不告警只是让状态行为不同。行为差异如下表来自 react18-batching-patternssetState 所在位置React 17React 18React 事件处理器批处理批处理相同setTimeout立即重渲染批处理Promise .then() / .catch()立即重渲染批处理async/await立即重渲染批处理原生 addEventListener 回调立即重渲染批处理典型的静默错误模式// DANGEROUS PATTERN - worked in React 17, breaks in React 18 async handleClick() { this.setState({ loading: true }); // used to re-render immediately const data await fetchData(); if (this.state.loading) { // this.state.loading is STILL old value in React 18 this.setState({ data }); } }batching-fixer 把漏洞模式分为三类并给出不同处置Category Aawait 后读 this.state 做决策→ 重构为函数式 setState 或直接设置避免读取中间状态Category B顺序无关的状态更新→ 重构无需 flushSyncCategory C中间渲染必须对用户可见加载态、向导步骤→ 用flushSync强制同步渲染flushSync的导入位置有讲究来自react-dom而非react-dom/clientimport ReactDOM, { flushSync } from react-dom; // 或 import { flushSync } from react-dom;决策树固化在 Skill 中Code reads this.state after await? YES → Category A (silent state-read bug) → 重构 NO, but intermediate render must be visible to user? YES → Category C (flushSync needed) NO → Category B (refactor, no flushSync)Skill 特别警告flushSync 要克制使用它绕过 React 18 并发调度器强制同步重渲染滥用会抵消 React 18 的性能收益。默认偏好是重构优先只有当 UI 行为语义上依赖中间渲染时才用 flushSync且插入处必须加注释说明原因。5. react18-test-guardian测试套件修复与验证者react18-test-guardian.agent.md 的职责范围覆盖RTL v14 API 变更、自动批处理测试回归、StrictMode 双调用变更、act() 异步语义、Enzyme 重写。它不跑到零失败绝不停止。首要任务 - Enzyme 检测与重写Enzyme 无 React 18 支持所有 Enzyme 测试必须用 RTL 重写。核心哲学转变react18-enzyme-to-rtlEnzyme 测实现RTL 测行为——wrapper.state(count)断言内部状态在 RTL 中没有直接对应物必须改写为断言可见输出screen.getByText(Count: 3)。API 映射要点// shallow/mount → render // wrapper.find(button) → screen.getByRole(button) // button.simulate(click) → fireEvent.click(...) 或 await user.click(...) // wrapper.prop(disabled) → screen.getByRole(button)).toBeDisabled() // wrapper.state(count) → 断言渲染输出 // wrapper.instance().handleClick() → 通过 UI 触发RTL 查询优先级getByRole→getByLabelText→getByPlaceholderText→getByText→getByDisplayValue→getByAltText→getByTitle→getByTestId最后手段。优先getByRole顺带测试了可访问性。六大测试修复类型T1 act() 异步语义React 18 的 act() 对异步更新更严格需要await act(async () {...})或直接用 RTL 内置异步工具waitFor/findBy*T2 自动批处理测试失败fireEvent 后紧跟的、无 waitFor 包裹的中间状态断言都是回归候选T3 RTL v14 破坏性变更userEvent从同步变为异步——必须先const user userEvent.setup()再await user.click(...)T4 StrictMode 双调用React 18 双调用 render、constructor、getDerivedStateFromProps 等策略是「不要猜」——跑测试看实际次数再更新断言T5 自定义 render helper确保自定义 helper 使用 RTL 的 renderRTL v14 内部即 createRoot用 wrapper 选项包裹 Apollo MockedProvider 等T6 Apollo MockedProviderReact 18 下 mock 需要显式异步刷新用waitFor或findBy替代旧的 setTimeout flush 模式配套的「React 18 测试错误分诊表」非常实用例如Enzyme cannot find module react-dom/adapter→ 无 React 18 适配器 → 全量 RTL 重写Expected 2, received 1调用计数→ StrictMode 差异 → 跑测试取实际值userEvent.click is not a function→ RTL v14 API 变更 →userEvent.setup()await user.click()。6. 各 Agent 的内存协议小结除指挥官外其余五个 Agent 都维护各自的 memory keyauditor 用react18-audit-progress、dep-surgeon 用react18-deps-state、class-surgeon 用react18-class-surgery-progress逐文件 checkpoint、batching-fixer 用react18-batching-progress、test-guardian 用react18-test-state每次运行记录失败数。这套机制保证流水线在任何阶段被打断后都能精确续跑正是 README 宣传的「Memory-based resumable pipeline」。七个 Skill 的内容地图插件自带的知识资产以 Skill 形式沉淀供各 Agent 在执行时查阅Skill核心内容仓库路径react-audit-grep-patterns完整 grep 扫描命令库基础 flag 约定 按目标的引用文件skills/react-audit-grep-patterns/SKILL.mdreact18-batching-patterns批处理行为对照表、快速诊断决策树、flushSync 使用规则skills/react18-batching-patterns/SKILL.mdreact18-dep-compatibilityReact 18/19 依赖兼容矩阵 冲突解决决策树 --legacy-peer-deps规则skills/react18-dep-compatibility/SKILL.mdreact18-enzyme-to-rtlEnzyme → RTL 重写模板、查询优先级、Provider 包裹方式skills/react18-enzyme-to-rtl/SKILL.mdreact18-legacy-context跨文件迁移固定步骤、扫描命令、多 context 场景skills/react18-legacy-context/SKILL.mdreact18-lifecycle-patterns三个不安全生命周期方法的决策表、UNSAFE_ 前缀规则skills/react18-lifecycle-patterns/SKILL.mdreact18-string-refs字符串 refs → React.createRef() 参考实现skills/react18-string-refs/SKILL.md其中react18-dep-compatibility的兼容矩阵是一份可独立查阅的运维资料核心版本要求摘录如下包React 18 最低版本说明react/react-dom18.3.1精确锁定testing-library/react14.0.0RTL 13 内部用 ReactDOM.renderR18 下损坏testing-library/user-event14.0.0v13 同步、v14 异步API 变更apollo/client3.8.03.8 引入 useSyncExternalStore 支持并发模式emotion/react11.10.011.10 起支持 React 18 并发模式react-router-domv6.0.0v5 → v6 是破坏性迁移需单独冲刺react-redux8.0.0v7 仅在 legacy root 下可用reduxjs/toolkit1.9.01.9 针对 React 18 测试tanstack/react-query4.0.0v3 不支持并发模式react-hook-form7.0.0v6 有并发模式问题react-dnd16.0.0v15 及以下有 R18 并发模式问题peer 冲突解决决策树先确认该包是否有 React 18 支持版本 → 有则安装最低兼容版 → 没有则判断是否关键 → 关键则查 issue/branch/PR最后手段--legacy-peer-deps并记录原因不关键则考虑移除该包。为什么 16/17 → 18 比 18 → 19 更难指挥官文档专门用一节解释这个反直觉的事实这也是整套工具链存在价值的论据自动批处理setState 在 Promise 或 setTimeout 中原本触发立即重渲染现在合并批处理。类组件中「异步取数 → setState → 条件 setState」链条必定出错。旧生命周期方法16.3 已弃用但 React 16/17 在未启用 StrictMode 时静默调用不告警。从未用过 StrictMode 的代码库可能残留数百处这类方法。事件委托变更React 17 把事件从document移到根容器。从 16 直接小版本补丁升级到 18 的项目可能存在依赖 document 层监听 React 事件的document.addEventListener模式。旧版 Context在 16 和 17 中全程静默工作很多类组件重度代码库用它做主题或鉴权直到 React 19 才真正删除。而 18.3.1 的显式警告正是把这一切全部暴露出来的工具——这就是整套迁移以「零告警 18.3.1 基线」为目标的根本原因。关键能力清单结合 README 与各 Agent 定义该插件的能力边界可以归纳为专攻类组件重度代码库而非仅函数组件模式自动批处理问题检测与flushSync建议Enzyme 测试检测 完整 RTL 重写能力基于 memory 的可恢复流水线——可耐受中断对未完成迁移零容忍——一直跑到完全成功StrictMode 感知的测试修复Apollo Client、Emotion、react-router 兼容性处理迁移检查清单可直接复用指挥官文档末尾提供了一份完整检查清单是团队执行时的可勾选验收标准审计报告已生成.github/react18-audit.mdreact18.3.1 react-dom18.3.1 已安装testing-library/react14 已安装全部 peer 依赖已解决npm ls: 0 errorscomponentWillMount → componentDidMount / constructorcomponentWillReceiveProps → getDerivedStateFromProps / componentDidUpdatecomponentWillUpdate → getSnapshotBeforeUpdate / componentDidUpdate旧版 Context → createContext字符串 refs → React.createRef()findDOMNode → 直接 refsReactDOM.render → createRootReactDOM.hydrate → hydrateRoot自动批处理回归已识别并修复必要时 flushSync事件委托假设已审计全部测试通过0 failures构建成功零 React 18.3.1 弃用告警总结react18-upgrade插件把一次高危的 React 大版本升级工程化为「审计 → 依赖 → 类组件手术 → 批处理修复 → 测试验证」五个带门禁、带内存断点续传的阶段。六 Agent 各司其职、七 Skill 沉淀知识最终以「零弃用告警的 18.3.1 基线」作为 React 19 迁移的前置条件。对于持有多年类组件存量代码的团队这套工具链提供的不只是自动改写更是一套可审计、可复现、可验收的迁移方法论——其所有扫描命令、兼容矩阵、决策树与错误分诊表均可在 plugins/react18-upgrade 及对应的 agents 与 skills 目录中直接查阅复用。【免费下载链接】awesome-copilotCommunity-contributed instructions, agents, skills, and configurations to help you make the most of GitHub Copilot.项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-copilot创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考