一, 前言
目前 React 最新的版本是 16.7.0, 基于全新的 React Fiber 架构, 有众多激动人心的新功能. 由于是大版本升级, 考虑到业务的稳定性, 我们团队大概等了一年的时间, 终于鼓起勇气着手升级的事情, 特以此文来记录升级过程中遇到的坑.
二, 升级的好处
这次升级的目标是将 React 从版本 15.6.2 升级到 16.2.0. 原因是 16.2.0 为止引入了几个不错的新特性, 同时对现有代码的影响会相对较小, 风险可控. 比较吸引我的三个新特性如下:
文件大小减少 30%. 官网原文如下:
react + react-dom is 109 kb (34.8 kb gzipped), down from 161.7 kb (49.8 kb gzipped).
Error Boundaries, 可以将错误限制在可控范围, 不会引起整个页面的白屏
- class ErrorBoundary extends React.Component {
- constructor(props) {
- super(props);
- this.state = { hasError: false };
- }
- componentDidCatch(error, info) {
- // Display fallback UI
- this.setState({ hasError: true });
- // You can also log the error to an error reporting service
- logErrorToMyService(error, info);
- }
- render() {
- if (this.state.hasError) {
- // You can render any custom fallback UI
- return <h1>Something went wrong.</h1>;
- }
- return this.props.children;
- }
- }
- <ErrorBoundary>
- <MyWidget />
- </ErrorBoundary>
Fragments, 可以在 render 返回多个一级组件, 而不需要在外面包一个 div
- const Fragment = React.Fragment;
- <Fragment>
- <ChildA />
- <ChildB />
- <ChildC />
- </Fragment>
三, 升级遇到的问题
1, 依赖
项目中用到了 React Router 3 和 Redux. 原计划将 Router 升级到 v4, 但改动实在太大, 放弃了, 只是升级到支持 16 的版本. 其它升级的依赖如下:
2,React.PropTypes
这种写法已经不支持了, 要改成:
- // import {
- PropTypes
- } from 'React' 已废弃
- import PropTypes from 'prop-types';
- 3,ReactDOM.render
在生命周期函数里面, ReactDOM.render 会返回 null, 因此类似下面这样的代码就会报错
- function newInstance(props) {
- ...
- let loading = ReactDOM.render(<Loading {...props} />, div);
- return {
- show: loading.show, // Error, loading 为 null
- container: div,
- };
- }
4,setState(null) 不触发 render
如果需要强制刷新的话, 可以使用 this.forceUpdate()
上述的问题主要是 16.0.0 带来的问题, 更详尽的升级指南可以看这里的.
总结
总体来说, 升级没有遇到特别大的困难, 主要就是针对官方文档的 Breaking changes 部分, 进行全局搜索, 然后进行修改. 另外, 还有可能依赖的库用到了已经不支持的 API, 例如 PropTypes, 应对办法就是升级对应的库.
先聊到这里, 有其它疑问, 欢迎留言交流.
来源: https://segmentfault.com/a/1190000017540511