React Native 的未来与React Hooks

作者: 恋猫月亮 | 来源:发表于2019-04-14 22:33 被阅读82次

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

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

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

    一、现状

    相信大家对于 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 等内置包拆分,通过社区独立维护,并逐步模糊 ReactReact-Native 的界限。
    • 2、更新 JavaScriptCore 、upgrade 和 CLI 工具。
    • 3、支持 React Hooks
    • 4、修复了 FlatList 等列表控件中的诸多问题。

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

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

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

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

    题外话

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

    • 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 自带的 webViewnetinfoasync-storage 等插件替换到 react-native-community 下提供,并替换一些弃用 API 。

    2、第三方库不兼容 :

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

    • 升级后遇到 realm 库在 Xcode 上的编译错误错误,详细可见 GSYGithubAPP#66 ,虽然问题不大,可自行通过简单本地改库解决,这也是目前项目的升级还未合并到 master 的原因之一。

    • react-native-router-fluxreact-navigation 的升级版本需要相互对应,同时需要增加 react-native-gesture-handler 依赖,并且在 index.js 入口处提前导入来解决一些问题。

    • 各类第三方插件的 Android targetSdksupportSdk 等版本和依赖方式问题。

    3、node_module “黑洞”

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

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

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

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

    • 总结

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

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

    三、React Hooks

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

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

    • ReduxRedux 的状态管理设计,且由它衍生出的一系列后续和第三方插件,我个人觉得这是 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 Hooks 相关更详细的干货,推荐查阅:

    最后说说编码风格:

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

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

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

    跨平台完整项目与文章:

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

    其他文章

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

    我们还会再见吗?

    相关文章

      网友评论

        本文标题:React Native 的未来与React Hooks

        本文链接:https://www.haomeiwen.com/subject/xcsjwqtx.html