0
点赞
收藏
分享

微信扫一扫

React Native 的未来与React Hooks

近期和一些朋友聊到了 ​​React-Native​​ 的官方重构状态,而刚好近期发布的 0.59.x 系列版本中,上层设计出现了比较大的调整,结合体验之后的状态,就想聊聊 ​​React-Native​​ 的现状、新版本的升级体验、还有新支持的 React Hook 等特性。

本篇并不是源码解析和教程,更多是讨论和记录描述。笔者一直致力于 Android​React-Native​​Flutter​ 等大前端开发,有时也会写写 ​React​​Vue​,本篇文章也是希望能够和大家交流,可以的话欢迎提出问题或者建议,最后同样希望文章能对你有所启发。


皮一下,React-Native 项目发布4年多了,还没有 1.0 版本么(¬_¬)


React Native 的未来与React Hooks_github

一、现状

相信大家对于 ​​React-Native​​​ “要凉” 的第一印象,应该是来自于 Aribnb 的 ​​“为什么 Airbnb 放弃了 React Native”​​ ,如文中描述的 ​​React-Native​​ 确实会遇到一些性能瓶颈,但这取决于和谁对比,个人认为 代码是服务于业务的,抛开场景比性能的做法其实并不严谨。 关键还是在于你如何使用,并且官方与社区是否还活跃和优化。

先说我对跨平台的理解: 一套逻辑可以在多个平台运行,更多是避免各平台业务逻辑不统一,而对工作量的减轻是不明显!不明显!不明显的! 同时一个企业项目大了之后,一般也不会局限于一个框架之内。

事实上 Facebook 也并没有放弃 ​​React-Native​​ ,在经历  ​​《Facebook 正在重构 React Native,将重写大量底层》​​ 的官宣之后,“四舍五入”将近一年后的今天,底层重构虽然还没有正式发布,但是近期的新版本 0.59.x 也给出了不错的答卷。

新版本中主要有以下几点:

  • 1、减轻了​​React-Native​​​ 自身框架,将 webView 、viewPager、netinfo、async-storage 等内置包拆分,通过社区独立维护,并逐步模糊​​React​​​ 和​​React-Native​​ 的界限。
  • 2、更新 JavaScriptCore 、upgrade 和 CLI 工具。
  • 3、支持React Hooks
  • 4、修复了​​FlatList​​ 等列表控件中的诸多问题。

未来版本的重构主要目标有:

  • 1、减轻 JSBridge 的依赖。
  • 2、通过FabricUI架构,将​​Shadow​​​ 层、​​UIManager​​​ 、​​NativeModule​​ 从 Java 移到 C++ 中,从而支持双向的同步和异步渲染与调用

可以看出 0.59 版本中的重构和拆分,都是在为了下一步的重构做准备,更多具体的下一代重构内容分析,可以在京东的 ​​《庖丁解牛!深入剖析 React Native 下一代架构重构》​​ 中查阅,这里就不多赘述了。

同样在携程的项目中: ​​《携程开源RN开发框架CRN》​​ 文章也表示在第一时间更新到了 0.59.x 版本,现在还会觉得 ​​React-Native​​ “要凉” 了嘛?


题外话

如今的编程界里存在各种“党争”,比如前端中 ​​Vue​​​ 、​​React​​​ 、 ​​Angular​​​ ,跨平台的 ​​Cordova​​​ 、​​Weex​​​ 、 ​​React-Native​​​ 、​​Flutter​​ 等,而我在考虑选择框架时,一般会从以下几点优先级先后排序:

  • 1、框架的活跃度。
  • 2、你的业务需求复杂度。
  • 3、团队配置和团队成员技术风格。
  • 4、个人对框架的舒适度。


二、React-Native 0.59.x

在选择升级版本之前,我们需要了解 ​​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​​ 的版本升级,带来的问题主要有三类:

1、官方 API 的调整

一般这类问题都比较好解决,官方的更新文档也有详细说明,这次升级中主要是将原本 ​​React-Native​​​ 自带的 ​​webView​​​ 、​​netinfo​​​ 、 ​​async-storage​​ 等插件替换到 ​​react-native-community​​ 下提供,并替换一些弃用 API 。

2、第三方库不兼容 :

这也是 ​​React-Native​​​ 中比较头疼的问题,因为第三方包的维护参差不齐,基本上如果作者不维护或维护不及时,那就只能自己苦笑动手了,就像本次 ​​GSYGithubAPP​​ 在升级过程中就遇到有:

  • 升级后遇到 ​​realm​​ 库在 Xcode 上的编译错误错误,详细可见 GSYGithubAPP#66 ,虽然问题不大,可自行通过简单本地改库解决,这也是目前项目的升级还未合并到 ​​master​​ 的原因之一。
  • ​react-native-router-flux​​ 与 ​​react-navigation​​ 的升级版本需要相互对应,同时需要增加 ​​react-native-gesture-handler​​ 依赖,并且在 ​​index.js​​ 入口处提前导入来解决一些问题。
  • 各类第三方插件的 Android ​​targetSdk​​ 和 ​​supportSdk​​ 等版本和依赖方式问题。

3、node_module “黑洞”

这类问题属于看人品,比如 ​​GSYGithubAPP​​ 项目是从 0.57 升级到 0.59 的,而 ​​BackAndroid​​ 在 0.58 已经被完全弃用,其中项目刚好存在一个 ​​modal​​​ 插件使用了 ​​BackAndroid​​ ,虽然作者也更新了插件做兼容,但是····

在更新了插件之后,重新运行后却依旧报错?WTF,而明插件源码已经没有 ​​BackAndroid​​ 的痕迹,那错误哪里来的?

React Native 的未来与React Hooks_github_02

通过 Chrome 的 Debug 查看当前 ​​bundle​​​ 源码,最后发现居然真的有​​BackAndroid​​ 的存在,当时就判断妥妥的缓存问题。

在执行了无数遍的卸载 APP,关闭CLI,删除 ​​node_module​​​ 重装后,最终还是通过删除缓存 ​​rm -rf ~/.rncache​​​ 和 ​​rm -rf $TMPDIR/*​​​ ,再重新安装​​node_module​​ 运行才解决问题。

总结

其实这也是为什么我说 ​​React-Native​​ 等跨平台开发,其实并没有降低工作量的原因。跨平台解决的是逻辑统一维护,而开发中过程中,很多时候会遇到兼容开发的问题,并且平台之间的适配同样消耗时间。


我相信每个 ​​React-Native​​​ 开发人员都十分讨厌满屏幕的红色,所以不知哪一版开始, ​​React-Native​​ 把错误增加了红黑相间的效果(¬_¬)。


React Native 的未来与React Hooks_开源项目_03

三、React Hooks

​React Hooks​​ 其实也是我升级到 0.59 的目的之一,因为它确实是一个很有意思的设定。

React Native 的未来与React Hooks_android_04

事实上我并非严格意义上的前端人员,大部分时候我对 CSSES 的了解也不深入,但在 JS 的使用过程中有几个让我印象深刻的:

  • Redux :​​Redux​​ 的状态管理设计,且由它衍生出的一系列后续和第三方插件,我个人觉得这是 ​​React​​ 当初能快速的风靡的助力之一。
  • HOCES7 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​ 确实有着明显的优势:

  • 可以更好的减少我们的代码量。
  • 同时降低代码在生命周期执行过程中造成的阻塞。
  • 自定义 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 Native 的未来与React Hooks_github_05

关于 ​​React Hooks​​ 相关更详细的干货,推荐查阅:

  • 《react hook的初步研究》
  • 《React hook 不是魔法,是数组》

最后说说编码风格:

无论是 ​HOC​​ 、 ​React Hooks​​ 、​Redux​ 等,其实我觉得都不存在所谓最优解,具体选择使用还是得看业务场景,过度为了设计而设计,杀鸡用牛刀的后果就是很不顺手,而且还容易误伤

如果是个人开发,show 代码亮逼格这无可厚非,但如果是实际团队开发,最好还是需要考虑团队的合作选型,不然你写的代码只有你能维护,估计最后哭的还是自己。

好了,本篇到此结束!(///▽///)

跨平台完整项目与文章:
  • ​​Flutter 开源项目与文章​​
  • ​​React Native 开源项目与文章​​
  • ​​Weex 开源项目与文章​​


完整文章目录在项目首页 ReadMe


其他文章

​​《移动端跨平台开发的深度解析》​​

React Native 的未来与React Hooks_前端_06

举报

相关推荐

0 条评论