RN 升级纪要(0.52->0.59.10)

TL;DR

升级RN可以带来以下好处:

  1. Hot Reloading 支持函数组件(旧版只支持 extends Component 方式);
  2. React 版本升级到16.8.6,可以使用 hooks 等新 API;
  3. 自带支持 Typescript,只要用 .ts.tsx 后缀即可,无需改任何配置,与现有 js 文件可共存。

升级到 0.59 版本比 0.60 痛楚要小很多,只需要更改 App 构建配置以及部分原生组件的写法即可。

升级背景

事情的起因是谷歌宣布19年8月1号开始在Google Play上架的应用都必须支持64位体系,而RN版本对64位的支持从0.58才开始,而项目组使用的版本比这低,因此升级是在所难免的。考虑到升级后框架更稳定而且含有更多特性,事不宜迟马上开搞。

升级的第一个问题是该升到哪个版本。当前时间段最新的版本有0.59和0.60(吐槽下时隔四年RN还没1.0版本)。从0.60的 changelog 中我们发现有一个重大的 breaking change 就是 AndroidX support。这个改动不像支持64位体系那样改改编译参数就行,还必须改动原生代码,是个改动量非常大的升级(主要是针对第三方库以及项目中的原生代码改动较大),而特性并没有比 0.59 多太多,反而去掉了很多以前的内置组件,移到社区托管了。因此最终钦定 0.59.10 为升级目标版本。

对于用户以及开发人员而言,以下几点改动是比较明显的,即使不需要上架 Google Play 也可以参考一下以确定是否需要升级:

  1. Hot Reloading 支持函数组件(旧版只支持 extends Component 方式);
  2. React 版本升级到16.8.6,可以使用 hooks 等新 API;
  3. 自带支持 Typescript,只要用 .ts.tsx 后缀即可,无需改任何配置。

升级iOS

新版移除了 iOS 8.x 的支持,需要升级系统最低版本。另外,glog 依赖的名称变了。使用 Podfile的需要改动以下内容

-platform :ios, '8.0'
+platform :ios, '9.0'
-    pod 'GLog', :podspec => '../node_modules/react-native/third-party-podspecs/GLog.podspec'
+    pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'

新版的输入框组件(TextInput)类继承体系改了,若做了相关扩展需要同步修改

原生封装的组件改动可能较多,需要多进行测试(自定义以及第三方原生扩展)。

升级Android

升级RN依赖后 appcompat-v7 会使用 28.0.0 版本,和项目中已使用的版本冲突,可使用以下方式降级处理。

build.gradle

allprojects {
    configurations.all {
        resolutionStrategy {
            force "com.android.support:appcompat-v7:26.0.1"
            force "com.android.support:support-v4:26.0.1"
        }
    }
}

RN 原生扩展组件很多时候是依赖于具体 RN 版本的,需要到各自官网查看升级描述。

升级React

使用 babel 插件转换旧代码

由于 React 需要同步升级,而新版由于引入 fiber 渲染,原先的三个生命周期变得不再安全而计划废弃并且改了名字,需要进行替换。

  • componentWillMount
  • componentWillReceiveProps
  • componentWillUpdate

由于尚有部分第三方库未升级,不方便在项目中修改,故引入 babel 插件精心统一替换。需添加react-rename-unsafe-lifecycle插件;若需要使用装饰器语法(如搭配redux或mobx),需要添加@babel/plugin-proposal-decorators插件。

babel.config.js

module.exports = {
  presets: ['module:metro-react-native-babel-preset'],
  plugins: [
    'react-rename-unsafe-lifecycle',
    '@babel/plugin-proposal-decorators', { legacy: true }
  ]
};

package.json

{
  "dependencies": {
    "@babel/core": "^7.4.5",
    "@babel/runtime": "^7.4.5",
    "react": "16.8.6",
    "react-native": "0.59.10",
    "babel-plugin-react-rename-unsafe-lifecycle": "^1.0.4",
    "metro-react-native-babel-preset": "^0.54.1"
  }
}

虽然使用以上插件可以暂时运行,但在特殊场景下是不安全的,并且后续会废弃掉,因此后续应该持续跟进,把这些接口用新接口重写。

官方迁移说明

改写 componentWillMount()

  • 用于发起网络请求的移动到 componentDidMount()
  • 根据传入的 props 计算组件属性(this.xxx)的(同步),视情况移动到 constructor

改写 componentWillReceiveProps()

根据使用场景不同,按如下方式替换

  • 需要根据传入的 props 执行副作用,改用 componentDidUpdate()(注意state改变也会执行 componentDidUpdate,需多加判断)
  • 需要根据传入的 props 计算新state,参考 这里(比较少见)

改写 componentWillUpdate()

相关代码移动到 componentDidUpdate()shouldComponentUpdate()

React Native (js)

官方移除组件

由于升级后 RN 官方仓库进行过瘦身,很多基本功能都移到社区维护了,用到了的需要手动添加回来。大部分组件规划在 0.60 正式移除,0.59 还能继续用,可考虑下次升级再处理。

RN 移除的组件

准备废弃的组件列表

  • ImageStore
  • ListView
  • MaskedViewIOS
  • Slider
  • SwipeableListView
  • ViewPagerAndroid
  • WebView
  • AlertIOS
  • AsyncStorage
  • NetInfo

非公开接口

有部分接口旧版本是没有公开的,需要用的只能根据路径引用。新版对路径进行了调整,导致引用报错。以下接口在新版做了改动,但已通过公开接口暴露出来,可以直接 import { XXX } from "react-native" 使用。

  • ColorPropType
  • EdgeInsetsPropType
  • PointPropType
  • ViewPropTypes

行为变化的组件

这部分改动最麻烦,只能发现一个改一个。目前发现以下问题:

  • FlatList 初始化时不会调用 onEndReached
  • ScrollView 的 scrollTo 方法 y 坐标不支持负值,scrollTo({y: -100}) 和 scrollTo({y: -0}) 效果一样
  • WebView 的 onMessage 接收到的数据会被 encodeURIComponent 两次,可以通过添加 useWebKit 属性解决,恢复旧版行为
  • react-native-webview 是从 RN 核心中抽离的 webview 组件,webview 发送消息需要用 window.ReactNativeWebView.postMessage 方法,和旧版的 window.postMessage 方式差异太大,不兼容线上代码,暂不考虑
  • NativeModules 改成了只读,需要修改只能复制一份修改然后替换整个 NativeModules
  • 原生封装的UI组件导出的常量使用方式改变,例如原来是通过 UIManager.RCTWebView.Commands.goForward 访问,现在需要使用 UIManager.getViewManagerConfig('RCTWebView').Commands.goForward

整个升级流程下来还是挺顺畅的,处理原生的构建花了一点时间,后续 js 部分的修改很多时候只要看控制台报错就可以,提示还是很清晰的。

App能跑起来后,基本功能没太大问题,但某些小角落可能会出现一些交互异常甚至奔溃,主要都是因为组件的 API 或者行为改变引起,需要做好充分的回归测试。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271