React 16 → 17 渐进式升级
约 638 字大约 2 分钟
布欧-Lewyon
2026-05-15
React 17 被称为"渐进式升级版本",没有增加重大新功能,主要为 React 18 的并发模式做准备。
事件委托变更
React 17 将事件监听从 document 改为挂载到 React 根 DOM 节点。
// React 16:所有事件绑定在 document
document.addEventListener('click', handler) // 可能与 React 冲突
// React 17:事件绑定在 root DOM
const root = document.getElementById('root')
// 事件绑定在 root 上,而非 document
// 好处:嵌套 React 子树、与第三方库共存更容易迁移影响
// ❌ 如果在 document 上监听 stopPropagation 会受影响(React 16 会冒泡到 document)
// ✅ React 17 只在 root 节点上处理,不污染 document
// 嵌套 React(微前端场景):
// React 16:两个 React 应用事件互相干扰
// React 17:各 React 子树在自己的 root 上处理事件JSX 新转换
React 17 引入了新的 JSX 编译,不再需要显式 import React from 'react'。
// React 16(旧 JSX 转换)
import React from 'react'
function App() { return React.createElement('div', null, 'Hello') }
// React 17+(新 JSX 转换)
function App() { return <div>Hello</div> }
// 编译后自动注入 react/jsx-runtime,不需要手动 import React迁移步骤
// tsconfig.json
{
"compilerOptions": {
"jsx": "react-jsx" // 新转换
// "jsx": "react" // 旧转换
}
}# 删除所有文件中无用的 import React from 'react'
npx react-codemod update-react-imports移除一些 API
// React 17 已废弃(但还未移除):
// componentWillMount / componentWillUpdate / componentWillReceiveProps
// 改用 UNSAFE_ 前缀或迁移到 Hooks
// 事件池机制移除:
// React 16:e.target 在异步中为 null(事件对象池化)
e.persist() // React 16 需要手动调用
// React 17:事件对象池化机制已移除
// e.target 在异步中可正常访问升级清单
1. 事件委托:验证第三方库是否依赖 document 事件
2. JSX 转换:更新 tsconfig,运行 codemod
3. 移除废弃生命周期:UNSAFE_componentWillMount → componentDidMount
4. 移除 e.persist() 调用
5. 测试嵌套 React(微前端)场景小结
- React 17 内核变化小,主要为 React 18 的"渐进式升级"铺路。
- 事件委托从
document→ root DOM,减少冲突。 - JSX 新编译省去
import React样板代码。 - 事件池化移除,解决异步读取事件对象问题。
- 升级风险极低,兼容性好。
上一节:无(版本升级专题第一篇) 下一节:React 18 并发模式
