React Native 的將來與React Hooks

近期和一些朋友聊到了 React-Native 的官方重構狀態,而恰好近期發佈的 0.59.x 系列版本中,上層設計出現了比較大的調整,結合體驗以後的狀態,就想聊聊 React-Native 的現狀、新版本的升級體驗、還有新支持的 React Hook 等特性。html

本篇並非源碼解析和教程,更可能是討論和記錄描述。筆者一直致力於 AndroidReact-NativeFlutter 等大前端開發,有時也會寫寫 ReactVue,本篇文章也是但願可以和你們交流,能夠的話歡迎提出問題或者建議,最後一樣但願文章能對你有所啓發。前端

皮一下,React-Native 項目發佈4年多了,尚未 1.0 版本麼(¬_¬)node

1、現狀

相信你們對於 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 等內置包拆分,經過社區獨立維護,並逐步模糊 ReactReact-Native 的界限。
  • 二、更新 JavaScriptCore 、upgrade 和 CLI 工具。
  • 三、支持 React Hooks
  • 四、修復了 FlatList 等列表控件中的諸多問題。

將來版本的重構主要目標有:編程

  • 一、減輕 JSBridge 的依賴。
  • 二、經過 Fabric UI架構,將 Shadow 層、 UIManagerNativeModule 從 Java 移到 C++ 中,從而支持 雙向的同步和異步渲染與調用

能夠看出 0.59 版本中的重構和拆分,都是在爲了下一步的重構作準備,更多具體的下一代重構內容分析,能夠在京東的 《庖丁解牛!深刻剖析 React Native 下一代架構重構》 中查閱,這裏就很少贅述了。react-native

一樣在攜程的項目中: 《攜程開源RN開發框架CRN》 文章也表示在第一時間更新到了 0.59.x 版本,如今還會以爲 React-Native 「要涼」 了嘛?數組

題外話

現在的編程界裏存在各類「黨爭」,好比前端中 VueReactAngular ,跨平臺的 CordovaWeexReact-NativeFlutter 等,而我在考慮選擇框架時,通常會從如下幾點優先級前後排序:

  • 一、框架的活躍度。
  • 二、你的業務需求複雜度。
  • 三、團隊配置和團隊成員技術風格。
  • 四、我的對框架的溫馨度。

2、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 的版本升級,帶來的問題主要有三類:

一、官方 API 的調整

通常這類問題都比較好解決,官方的更新文檔也有詳細說明,此次升級中主要是將本來 React-Native 自帶的 webViewnetinfoasync-storage 等插件替換到 react-native-community 下提供,並替換一些棄用 API 。

二、第三方庫不兼容 :

這也是 React-Native 中比較頭疼的問題,由於第三方包的維護良莠不齊,基本上若是做者不維護或維護不及時,那就只能本身苦笑動手了,就像本次 GSYGithubAPP 在升級過程當中就遇到有:

  • 升級後遇到 realm 庫在 Xcode 上的編譯錯誤錯誤,詳細可見 GSYGithubAPP#66 ,雖然問題不大,可自行經過簡單本地改庫解決,這也是目前項目的升級還未合併到 master 的緣由之一。

  • react-native-router-fluxreact-navigation 的升級版本須要相互對應,同時須要增長 react-native-gesture-handler 依賴,而且在 index.js 入口處提早導入來解決一些問題。

  • 各種第三方插件的 Android targetSdksupportSdk 等版本和依賴方式問題。

三、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 把錯誤增長了紅黑相間的效果(¬_¬)。

3、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

其餘文章

《移動端跨平臺開發的深度解析》

咱們還會再見嗎?
相關文章
相關標籤/搜索