近期和一些朋友聊到了 React-Native 的官方重構狀態,而剛好近期發布的 0.59.x 系列版本中,上層設計出現了比較大的調整,結合體驗之後的狀態,就想聊聊 React-Native 的現狀、新版本的升級體驗、還有新支持的 React Hook 等特性。
React-Native
本篇並不是源碼解析和教程,更多是討論和記錄描述。筆者一直致力於 Android 、React-Native、Flutter 等大前端開發,有時也會寫寫 React 和 Vue,本篇文章也是希望能夠和大家交流,可以的話歡迎提出問題或者建議,最後同樣希望文章能對你有所啟發。
Android
Flutter
React
Vue
皮一下,React-Native 項目發布4年多了,還沒有 1.0 版本么(?_?)
相信大家對於 React-Native 「要涼」 的第一印象,應該是來自於 Aribnb 的 「為什麼 Airbnb 放棄了 React Native」 ,如文中描述的 React-Native 確實會遇到一些性能瓶頸,但這取決於和誰對比,個人認為 代碼是服務於業務的,拋開場景比性能的做法其實並不嚴謹。 關鍵還是在於你如何使用,並且官方與社區是否還活躍和優化。
先說我對跨平台的理解: 一套邏輯可以在多個平台運行,更多是避免各平台業務邏輯不統一,而對工作量的減輕是不明顯!不明顯!不明顯的! 同時一個企業項目大了之後,一般也不會局限於一個框架之內。
事實上 Facebook 也並沒有放棄 React-Native ,在經歷 《Facebook 正在重構 React Native,將重寫大量底層》 的官宣之後,「四捨五入」將近一年後的今天,底層重構雖然還沒有正式發布,但是近期的新版本 0.59.x 也給出了不錯的答卷。
新版本中主要有以下幾點:
FlatList
未來版本的重構主要目標有:
Shadow
UIManager
NativeModule
可以看出 0.59 版本中的重構和拆分,都是在為了下一步的重構做準備,更多具體的下一代重構內容分析,可以在京東的 《庖丁解牛!深入剖析 React Native 下一代架構重構》 中查閱,這裡就不多贅述了。
同樣在攜程的項目中: 《攜程開源RN開發框架CRN》 文章也表示在第一時間更新到了 0.59.x 版本,現在還會覺得 React-Native 「要涼」 了嘛?
題外話 : 如今的編程界里存在各種「黨爭」,比如前端中 Vue 、React 、 Angular ,跨平台的 Cordova 、Weex 、 React-Native 、Flutter 等,而我在考慮選擇框架時,一般會從以下幾點優先順序先後排序: - 1、框架的活躍度。 - 2、你的業務需求複雜度。 - 3、團隊配置和團隊成員技術風格。 - 4、個人對框架的舒適度。
題外話 :
Angular
Cordova
Weex
在選擇升級版本之前,我們需要了解 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 的版本升級,帶來的問題主要有三類:
0.57.8
0.59.4
1、官方 API 的調整 :
一般這類問題都比較好解決,官方的更新文檔也有詳細說明,這次升級中主要是將原本 React-Native 自帶的 webView 、netinfo 、 async-storage 等插件替換到 react-native-community 下提供,並替換一些棄用 API 。
webView
netinfo
async-storage
2、第三方庫不兼容 :
這也是 React-Native 中比較頭疼的問題,因為第三方包的維護參差不齊,基本上如果作者不維護或維護不及時,那就只能自己苦笑動手了,就像本次 GSYGithubAPP 在升級過程中就遇到有:
GSYGithubAPP
realm
master
react-native-router-flux
react-navigation
react-native-gesture-handler
index.js
targetSdk
supportSdk
3、node_module 「黑洞」 :
這類問題屬於看人品,比如 GSYGithubAPP 項目是從 0.57 升級到 0.59 的,而 BackAndroid 在 0.58 已經被完全棄用,其中項目剛好存在一個 modal 插件使用了 BackAndroid ,雖然作者也更新了插件做兼容,但是····
BackAndroid
modal
在更新了插件之後,重新運行後卻依舊報錯?WTF,而明插件源碼已經沒有 BackAndroid 的痕迹,那錯誤哪裡來的?
通過 Chrome 的 Debug 查看當前 bundle 源碼,最後發現居然真的有BackAndroid 的存在,當時就判斷妥妥的緩存問題。
bundle
在執行了無數遍的卸載 APP,關閉CLI,刪除 node_module 重裝後,最終還是通過刪除緩存 rm -rf ~/.rncache 和 rm -rf $TMPDIR/* ,再重新安裝node_module 運行才解決問題。
node_module
rm -rf ~/.rncache
rm -rf $TMPDIR/*
其實這也是為什麼我說 React-Native 等跨平台開發,其實並沒有降低工作量的原因。跨平台解決的是邏輯統一維護,而開發中過程中,很多時候會遇到兼容開發的問題,並且平台之間的適配同樣消耗時間。
我相信每個 React-Native 開發人員都十分討厭滿屏幕的紅色,所以不知哪一版開始, React-Native 把錯誤增加了紅黑相間的效果(?_?)。
React Hooks 其實也是我升級到 0.59 的目的之一,因為它確實是一個很有意思的設定。
React Hooks
事實上我並非嚴格意義上的前端人員,大部分時候我對 CSS 和 ES 的了解也不深入,但在 JS 的使用過程中有幾個讓我印象深刻的:
Redux
最後就是本文主角 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 。
useReducer
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 等行為。
if
for
關於 React Hooks 相關更詳細的乾貨,推薦查閱:
無論是 HOC 、 React Hooks 、Redux 等,其實我覺得都不存在所謂最優解,具體選擇使用還是得看業務場景,過度為了設計而設計,殺雞用牛刀的後果就是很不順手,而且還容易誤傷。
HOC
如果是個人開發,show 代碼亮逼格這無可厚非,但如果是實際團隊開發,最好還是需要考慮團隊的合作選型,不然你寫的代碼只有你能維護,估計最後哭的還是自己。
好了,本篇到此結束!(///▽///)
完整文章目錄在項目首頁 ReadMe
《移動端跨平台開發的深度解析》
推薦閱讀: