近期和一些朋友聊到了 React-Native
的官方重构状态,而恰好近期发布的 0.59.x 系列版本中,上层设计出现了比较大的调整,结合体验以后的状态,就想聊聊 React-Native
的现状、新版本的升级体验、还有新支持的 React Hook 等特性。html
本篇并非源码解析和教程,更可能是讨论和记录描述。笔者一直致力于 Android
、React-Native
、Flutter
等大前端开发,有时也会写写 React
和 Vue
,本篇文章也是但愿可以和你们交流,能够的话欢迎提出问题或者建议,最后一样但愿文章能对你有所启发。前端
皮一下,React-Native 项目发布4年多了,尚未 1.0 版本么(¬_¬)node
相信你们对于 React-Native
“要凉” 的第一印象,应该是来自于 Aribnb 的 “为何 Airbnb 放弃了 React Native” ,如文中描述的 React-Native
确实会遇到一些性能瓶颈,但这取决于和谁对比,我的认为 代码是服务于业务的,抛开场景比性能的作法其实并不严谨。 关键仍是在于你如何使用,而且官方与社区是否还活跃和优化。react
先说我对跨平台的理解: 一套逻辑能够在多个平台运行,更可能是避免各平台业务逻辑不统一,而对工做量的减轻是不明显!不明显!不明显的! 同时一个企业项目大了以后,通常也不会局限于一个框架以内。git
事实上 Facebook 也并无放弃 React-Native
,在经历 《Facebook 正在重构 React Native,将重写大量底层》 的官宣以后,“四舍五入”将近一年后的今天,底层重构虽然尚未正式发布,可是近期的新版本 0.59.x 也给出了不错的答卷。github
新版本中主要有如下几点:web
React-Native
自身框架,将 webView 、viewPager、netinfo、async-storage 等内置包拆分,经过社区独立维护,并逐步模糊 React
和 React-Native
的界限。FlatList
等列表控件中的诸多问题。将来版本的重构主要目标有:编程
Shadow
层、 UIManager
、NativeModule
从 Java 移到 C++ 中,从而支持 双向的同步和异步渲染与调用 。能够看出 0.59 版本中的重构和拆分,都是在为了下一步的重构作准备,更多具体的下一代重构内容分析,能够在京东的 《庖丁解牛!深刻剖析 React Native 下一代架构重构》 中查阅,这里就很少赘述了。react-native
一样在携程的项目中: 《携程开源RN开发框架CRN》 文章也表示在第一时间更新到了 0.59.x 版本,如今还会以为 React-Native
“要凉” 了嘛?数组
题外话 :
现在的编程界里存在各类“党争”,好比前端中
Vue
、React
、Angular
,跨平台的Cordova
、Weex
、React-Native
、Flutter
等,而我在考虑选择框架时,通常会从如下几点优先级前后排序:
- 一、框架的活跃度。
- 二、你的业务需求复杂度。
- 三、团队配置和团队成员技术风格。
- 四、我的对框架的温馨度。
在选择升级版本以前,咱们须要了解 React-Native
中版本是有 0.A.B 的大 A 小 B 版本号设定,而在 React-Native
使用过程当中个人一个感觉就是:
在作 React-Native
的版本选择或升级时,最好不要选用 0.A.0 版本,好比 0.59.0;我通常会选择大版本以后的小版本迭代,如 0.59.4 版本去升级更新,这样的版本相对更稳定,能够少躺一些问题。
而后 React-Native
的版本升级一直是个头大的问题,我通常会先在本身的开源项目中躺坑,本次在个人开源项目 GSYGithubAPP 中,是从 0.57.8
直接升级到 0.59.4
版本,结果如预期通常并不顺利,而通常 React-Native
的版本升级,带来的问题主要有三类:
一、官方 API 的调整 :
通常这类问题都比较好解决,官方的更新文档也有详细说明,此次升级中主要是将本来 React-Native
自带的 webView
、netinfo
、 async-storage
等插件替换到 react-native-community 下提供,并替换一些弃用 API 。
二、第三方库不兼容 :
这也是 React-Native
中比较头疼的问题,由于第三方包的维护良莠不齐,基本上若是做者不维护或维护不及时,那就只能本身苦笑动手了,就像本次 GSYGithubAPP
在升级过程当中就遇到有:
升级后遇到 realm
库在 Xcode 上的编译错误错误,详细可见 GSYGithubAPP#66 ,虽然问题不大,可自行经过简单本地改库解决,这也是目前项目的升级还未合并到 master
的缘由之一。
react-native-router-flux
与 react-navigation
的升级版本须要相互对应,同时须要增长 react-native-gesture-handler
依赖,而且在 index.js
入口处提早导入来解决一些问题。
各种第三方插件的 Android targetSdk
和 supportSdk
等版本和依赖方式问题。
三、node_module “黑洞” :
这类问题属于看人品,好比 GSYGithubAPP
项目是从 0.57 升级到 0.59 的,而 BackAndroid
在 0.58 已经被彻底弃用,其中项目恰好存在一个 modal
插件使用了 BackAndroid
,虽然做者也更新了插件作兼容,可是····
在更新了插件以后,从新运行后却依旧报错?WTF,而明插件源码已经没有 BackAndroid
的痕迹,那错误哪里来的?
经过 Chrome 的 Debug 查看当前 bundle
源码,最后发现竟然真的有BackAndroid
的存在,当时就判断妥妥的缓存问题。
在执行了无数遍的卸载 APP,关闭CLI,删除 node_module
重装后,最终仍是经过删除缓存 rm -rf ~/.rncache
和 rm -rf $TMPDIR/*
,再从新安装node_module
运行才解决问题。
其实这也是为何我说 React-Native
等跨平台开发,其实并无下降工做量的缘由。跨平台解决的是逻辑统一维护,而开发中过程当中,不少时候会遇到兼容开发的问题,而且平台之间的适配一样消耗时间。
我相信每一个
React-Native
开发人员都十分讨厌满屏幕的红色,因此不知哪一版开始,React-Native
把错误增长了红黑相间的效果(¬_¬)。
React Hooks
其实也是我升级到 0.59 的目的之一,由于它确实是一个颇有意思的设定。
事实上我并不是严格意义上的前端人员,大部分时候我对 CSS 和 ES 的了解也不深刻,但在 JS 的使用过程当中有几个让我印象深入的:
Redux :Redux
的状态管理设计,且由它衍生出的一系列后续和第三方插件,我我的以为这是 React
当初能快速的风靡的助力之一。
HOC 和 ES7 Decorators :事实上这应该也包含在 Redux
里, 可是 HOC + Decorators 快速实现相似切面编程的效果,这无疑让 Java 开发的我感到亲切。
最后就是本文主角 React Hooks
了,React Hooks
也算是比较新的概念,关于 React Hooks
的我推荐这篇文章: 《【React深刻】从Mixin到HOC再到Hook》 ,文中很好的描述了 React
开发风格的发展和对比。
而对于 React Hooks
能在这么早就引入到 React-Native
中,给个人感受就是 Facebook 团队在致力于模糊 React
开发者在 Web 和 App 之间的边界,同时这也是为了丰富 React
开发者的生态吧。
而对于 React Hooks
,在个人理解上而言,函数式编程可能更贴近“将来”的形态(虽然我并不特别肯定),而 React Hooks
确实有着明显的优点:
回归到具体使用, React Hooks
其中最经常使用默认接口有 :
useState
可让你在函数中快速添加状态useEffect
让你快速添加生命周期处理useImperativeHandle
快速对外暴露接口这些内置 Hook 能够在必定程度上节省你的代码量,而且提供清晰的状态管理逻辑,同时利用官方的 useReducer
,以下方代码,更能够快速写出一个伪 Redux
。
import React, {Component, useReducer, useRef, useImperativeHandle, forwardRef} from 'react';
import {Text, View, TouchableOpacity,} from 'react-native';
const initialState = {count: 0};
function reducer(state, action) {
switch (action.type) {
case 'reset':
return initialState;
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
return state;
}
}
export function DemoCounter({initialCount}) {
const [state, dispatch] = useReducer(reducer, {count: initialCount});
return (
<View>
<Text>Count: {state.count}</Text>
<TouchableOpacity onPress={() => dispatch({type: 'reset'})}>
<Text>Reset</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => dispatch({type: 'increment'})}>
<Text>+</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => dispatch({type: 'decrement'})}>
<Text>-</Text>
</TouchableOpacity>
</View>
)
}
复制代码
对于 React Hooks
,结合查阅源码和文章简单理解,就在渲染以前利用系列的钩子,而 Hooks 内部利用了数组 ,实现状态数据的顺序更新。
因此官方也表示了,Hooks 不能在循环或者条件判断中使用,这属于一种约定,由于 Hooks 内的数组每次都是顺序的调用的,若是在条件判断中打乱了顺序,将致使游标没法匹配到正确的数据,因此约定了不要在 if
或者 for
中使用 useState
等行为。
关于 React Hooks
相关更详细的干货,推荐查阅:
不管是 HOC
、 React Hooks
、Redux
等,其实我以为都不存在所谓最优解,具体选择使用仍是得看业务场景,过分为了设计而设计,杀鸡用牛刀的后果就是很不顺手,并且还容易误伤。
若是是我的开发,show 代码亮逼格这无可厚非,但若是是实际团队开发,最好仍是须要考虑团队的合做选型,否则你写的代码只有你能维护,估计最后哭的仍是本身。
好了,本篇到此结束!(///▽///)
完整文章目录在项目首页 ReadMe