日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

一份 2.5k star 的《React 开发思想纲领》

發(fā)布時間:2023/12/9 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一份 2.5k star 的《React 开发思想纲领》 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

大家好,我是若川。持續(xù)組織了6個月源碼共讀活動,感興趣的可以點此加我微信 ruochuan12?參與,每周大家一起學(xué)習(xí)200行左右的源碼,共同進步。同時極力推薦訂閱我寫的《學(xué)習(xí)源碼整體架構(gòu)系列》?包含20余篇源碼文章。歷史面試系列

翻譯自:https://github.com/mithi/react-philosophies[1]?2.5k star
原文作者:mithi[2]
已獲作者授權(quán)

概要

  • 介紹

  • 最低要求

  • 面向幸福設(shè)計

  • 性能優(yōu)化技巧

  • 測試原則

  • 🧘 0. 介紹

    《React 開發(fā)思想綱領(lǐng)》是:

    • 我開發(fā) React 時的一些思考

    • 每當我 review 他人或自己的代碼時自然而然會思考的東西

    • 僅僅作為參考和建議,并非嚴格的要求

    • 會隨著我的經(jīng)驗不斷更新

    • 大多數(shù)技術(shù)點是基礎(chǔ)的重構(gòu)方法論,SOLID 原則以及極限編程等思想的變體,僅僅是在 React 中的實踐而已 🙂

    你可能會覺得我寫的這些非常基礎(chǔ)。但以下示例都來自一些復(fù)雜大型項目的線上代碼。

    《React 開發(fā)思想綱領(lǐng)》的靈感來源于我實際開發(fā)中遇到的各種場景。

    🧘 1. 最低要求

    1.1 計算機比你更「智能」

  • 使用 ESLint 來靜態(tài)分析你的代碼,開啟 rule-of-hooks 和 exhaustive-deps 這兩個規(guī)則來捕獲 React 錯誤。

  • 開啟 JS 嚴格模式吧,都 2202 年了。

  • 直面依賴,解決在useMemo,useCallback 和 useEffect 上 exhaustive-deps 規(guī)則提示的 warning 或 error 問題。可以將最新的值掛在 ref 上來保證這些 hook 在回調(diào)中拿到的都是最新的值,同時避免不必要的重新渲染。

  • 使用 map 批量渲染組件時,都加上 key。

  • 只在最頂層使用 hook,不要在循環(huán)、條件或嵌套語句中使用 hook。

  • 理解不能對已經(jīng)卸載的組件執(zhí)行狀態(tài)更新的控制臺警告。

  • 給不同層級的組件都添加錯誤邊界(Error Boundary)來防止白屏,還可以用它來向錯誤監(jiān)控平臺(比如 Sentry)上報錯誤,并設(shè)置報警。

  • 不要忽略了控制臺中打印的錯誤和警告。

  • 記得要 tree-shaking!

  • 使用 Prettier 來保證代碼的格式化一致性!

  • 使用 Typescript 和 NextJS這樣的框架來提升開發(fā)體驗。

  • 強烈推薦 Code Climate(或其他類似的)開源庫。這類工具會自動檢測代碼異味(Code Smell,代碼中的任何可能導(dǎo)致深層次問題的癥狀),它可以促使我去處理項目里留下的技術(shù)債。

  • 1.2 Code is just a necessary evil

    譯者注:程序員的目標是解決客戶的問題,代碼只是副產(chǎn)品

    1.2.1 先思考,再加依賴

    依賴加的越多,提供給瀏覽器的代碼就越多。捫心問問自己,你是否真的使用了某個庫的 feature?

    🙈 ?你真的需要它嗎? 看看這些你可能不需要的依賴

  • 你是否真的需要 Redux?有可能需要,但其實 React 本身也是一個狀態(tài)管理庫。

  • 你是否真的需要 Apollo client?Apollo client 有許多很強大的功能,比如數(shù)據(jù)規(guī)范化。但使用的同時也會顯著提高包體積。如果你的項目使用的并非是 Apollo client 特有的 feature,可以考慮使用一些輕量的庫來替代,比如 react-query 或 SWR(或者根本不用)。

  • Axios 呢?Axios 是一個很棒的庫,它的一些特性不容易通過原生的 fetch API 來復(fù)刻。但是如果使用 Axios 只是因為它有更好的 API,完全可以考慮在 fetch 上做一層封裝(比如 redaxios 或自己實現(xiàn))。取決于你的 App 是否真正地使用了 Axios 的核心 feature。

  • Decimal.js 呢?或許 Big.js 或者其他輕量的庫就足夠了。

  • Lodash/underscoreJS呢?推薦你看看【你不需要系列之“你不需要 Lodash/Underscore”】[3]

  • MomentJS呢?【你不需要系列之“你不需要 Momentjs”】[4]

  • 你不需要為了主題(淺色/深色模式)而使用 Context,考慮下用 css 變量 代替。

  • 你甚至不需要 Javascript,CSS 也足夠強大。【你不需要系列之“你不需要 JavaScript”】[5]

  • 1.2.2 不要自作聰明,提前設(shè)計

    "我們的軟件在未來會如何迭代?可能會這樣或者那樣,如果在當下就開始往這些方向進行代碼設(shè)計,這就叫 future-proof(防過時,面向未來編程)。"

    不要這樣搞! 應(yīng)該在面臨需求的時候再去實現(xiàn)相應(yīng)功能,而不是在你預(yù)見到可能需要的時候。代碼應(yīng)該越少越好!

    1.3 發(fā)現(xiàn)了就優(yōu)化它

    1.3.1 檢測代碼異味(Code Smell),并在必要時對其進行處理。

    當你意識到某個地方出現(xiàn)了問題,那就馬上處理掉。但如果當前不容易修復(fù),或者沒有時間,那請至少添加一條注釋(FIXME 或者 TODO),附上對該問題的簡要描述。來讓項目里的每個人都知道這里有問題,讓他們意識到當他們遇到這樣的情況時也該這樣做。

    🙈 來看看這些容易發(fā)現(xiàn)的代碼異味

    • ? 定義了很多參數(shù)的函數(shù)或方法

    • ? 難以理解的,返回 Boolean 值的邏輯

    • ? 單個文件中代碼行數(shù)太多

    • ? 在語法上可能相同(但格式化可能不同)的重復(fù)代碼

    • ? 可能難以理解的函數(shù)或方法

    • ? 定義了大量函數(shù)或方法的類/組件

    • ? 單個函數(shù)或方法中的代碼行數(shù)太多

    • ? 具有大量返回語句的函數(shù)或方法

    • ? 不完全相同但代碼結(jié)構(gòu)類似的重復(fù)代碼(比如變量名可能不同)

    切記,代碼異味并不一定意味著代碼需要修改,它只是告訴你,你應(yīng)該可以想出更好的方式來實現(xiàn)相同的功能。

    1.3.2 無情的重構(gòu)。簡單比復(fù)雜好。

    💁?♀? 小技巧: 簡化復(fù)雜的條件語句,最好能提前 return。

    🙈 提前 return 的示例

    #???不太好if?(loading)?{return?<LoadingScreen?/> }?else?if?(error)?{return?<ErrorScreen?/> }?else?if?(data)?{return?<DataScreen?/> }?else?{throw?new?Error('This?should?be?impossible') }#???推薦if?(loading)?{return?<LoadingScreen?/> }if?(error)?{return?<ErrorScreen?/> }if?(data)?{return?<DataScreen?/> }throw?new?Error('This?should?be?impossible')

    💁?♀? 小技巧: 比起傳統(tǒng)的循環(huán)語句,鏈式的高階函數(shù)更優(yōu)雅

    如果沒有明顯的性能差異,盡量使用鏈式的高階函數(shù)(map, filter, find, findIndex, some等) 來代替?zhèn)鹘y(tǒng)的循環(huán)語句。

    1.4 你可以做的更好

    💁?♀? 小技巧: 可以在 setState 時傳入回調(diào)函數(shù),所以沒必要把 state 作為一個依賴項

    你不用把 setState 和 dispatch 放在 useEffect 和 useCallback 這些 hook 的依賴數(shù)組中。ESLint 也不會給你提示,因為 React 已經(jīng)確保了它們不會出錯。

    #???不太好 const?decrement?=?useCallback(()?=>?setCount(count?-?1),?[setCount,?count]) const?decrement?=?useCallback(()?=>?setCount(count?-?1),?[count])#???推薦 const?decrement?=?useCallback(()?=>?setCount(count?=>?(count?-?1)),?[])

    💁?♀? 小技巧: 如果你的 useMemo 或 useCallback 沒有任何依賴,那你可能用錯了

    #???不太好 const?MyComponent?=?()?=>?{const?functionToCall?=?useCallback(x:?string?=>?`Hello?${x}!`,[])const?iAmAConstant?=?useMemo(()?=>?{?return?{x:?5,?y:?2}?},?[])/*?接下來可能會用到?functionToCall?和?iAmAConstant?*/ }#???推薦 const?I_AM_A_CONSTANT?=??{?x:?5,?y:?2?} const?functionToCall?=?(x:?string)?=>?`Hello?${x}!` const?MyComponent?=?()?=>?{/*?接下來可能會用到?functionToCall?和?I_AM_A_CONSTANT?*/ }

    💁?♀? 小技巧: 巧用 hook 封裝自定義的 context,會提升 API 可讀性

    它不僅看起來更清晰,而且你只需要 import 一次,而不是兩次。

    ? 不太好

    //?你每次需要?import?兩個變量 import?{?useContext?}?from?'react'; import?{?SomethingContext?}?from?'some-context-package';function?App()?{const?something?=?useContext(SomethingContext);?//?看起來?ok,但可以更好//?... }

    ? 推薦

    //?在另一個文件中,定義這個?hook function?useSomething()?{const?context?=?useContext(SomethingContext);if?(context?===?undefined)?{throw?new?Error('useSomething?must?be?used?within?a?SomethingProvider');}return?context; }//?你只需要?import?一次 import?{?useSomething?}?from?'some-context-package';function?App()?{const?something?=?useSomething();?//?看起來會更清晰//?... }

    💁?♀? 小技巧: 在寫組件之前,先思考該怎么用它

    設(shè)計 API 很難,README 驅(qū)動開發(fā)(RDD)是個很有用的辦法,可以幫助你設(shè)計出更好的 API。并不是說應(yīng)該無腦使用 RDD,但它背后的思想是很值得學(xué)習(xí)的。我自己發(fā)現(xiàn),在設(shè)計實現(xiàn)組件 API 之前,使用 RDD 通常比不用時設(shè)計地更好。

    🧘 2. 面向幸福設(shè)計

    太長不看版

  • 💖 通過刪除冗余的狀態(tài)來減少狀態(tài)管理的復(fù)雜性。

  • 💖 “傳遞香蕉,而不是拿著香蕉的大猩猩和整個叢林“(意思是組件要什么傳什么,不要傳大對象)。

  • 💖 讓你的組件小而簡單 —— 單一職責原則。

  • 💖 復(fù)制比錯誤的抽象要“便宜”的多(避免提早/不恰當?shù)脑O(shè)計)。

  • 避免 prop 層層傳遞(又叫 prop 鉆取,prop drilling)。Context 不是解決狀態(tài)共享問題的銀彈。

  • 將巨大的 useEffect 拆分成獨立的小 useEffect。

  • 將邏輯提取出來都放到 hook 和工具函數(shù)中。

  • useCallback, useMemo 和 useEffect 依賴數(shù)組中的依賴項最好都是基本類型。

  • 不要在 useCallback, useMemo 和 useEffect 中放入太多的依賴項。

  • 為了簡單起見,如果你的狀態(tài)依賴其他狀態(tài)和上次的值,考慮使用 useReducer,而不是使用很多個 useState。

  • Context 不一定要放在整個 app 的全局。把 Context 放在組件樹中盡可能低的位置。同樣的道理,你的變量,注釋和狀態(tài)(和普通代碼)也應(yīng)該放在靠近他們被使用的地方。

  • 💖 2.1 刪除冗余的狀態(tài)來減少狀態(tài)管理的復(fù)雜性

    冗余的狀態(tài)指可以通過其他狀態(tài)經(jīng)過推導(dǎo)得到的狀態(tài),不需要單獨維護(類似 Vue computed),當你有冗余的狀態(tài)時,一些狀態(tài)可能會丟失同步性,在面對復(fù)雜交互的場景時,你可能會忘記更新它們。

    刪除這些冗余的狀態(tài),除了避免同步錯誤外,這樣的代碼也更容易維護和推理,而且代碼更少。

    💖 2.2 “傳遞香蕉,而不是拿著香蕉的大猩猩和整個叢林“

    為了避免掉入這種坑,最好將基本類型(boolean, string, number 等)作為 props 傳遞。(傳遞基本類型也能更好的讓你使用 React.memo 進行優(yōu)化)

    組件應(yīng)該僅僅只了解和它運作相關(guān)的內(nèi)容就足夠了。應(yīng)該盡可能地與其他組件產(chǎn)生協(xié)作,而不需要知道它們是什么或做什么。

    這樣做的好處是,組件間的耦合會更松散,依賴程度會更低。低耦合更利于組件修改,替換和移除,而不會影響其他組件。

    💖 2.3 讓你的組件小而簡單

    什么是「單一職責原則」?

    一個組件應(yīng)該有且只有一個職責。應(yīng)該盡可能的簡單且實用,只有完成其職責的責任。

    具有各種職責的組件很難被復(fù)用。幾乎不可能只復(fù)用它的部分能力,很容易與其他代碼耦合在一起。那些抽離了邏輯的組件,改起來負擔不大而且復(fù)用性更強。

    如何判斷一個組件是否符合單一職責?

    可以試著用一句話來描述這個組件。如果它只負責一個職責,描述起來會很簡單。如果描述中出現(xiàn)了“和“或“或”,那么這個組件很大概率不是單一職責的。

    檢查組件的 state,props 和 hooks,以及組件內(nèi)部聲明的變量和方法(不應(yīng)該太多)。問問自己:是否這些內(nèi)容必須組合到一起這個歌組件才能工作?如果有些不需要,可以考慮把它們抽離到其他地方,或者把這個大組件拆解成小組件。

    🧘 3. 性能優(yōu)化技巧

  • 如果你覺得應(yīng)用速度慢,就應(yīng)該做一次基準測試(benchmark)來證明。 "面對模凌兩可的情況,拒絕猜測。" 多使用 Chrome 插件 - React 開發(fā)者工具的 profiler!

  • useMemo 主要用在大開銷的計算上。

  • 如果你打算使用 React.memo, useMemo, 和 useCallback 來減少重新渲染,它們不該有過多的依賴項,且這些依賴項最好都是基本類型。

  • 確保你清楚代碼里 React.memo, useCallback 或 useMemo 它們都是為了什么而使用的(是否真的能防止重新渲染?是否能證明在這些場景中真的可以顯著提高性能? Memoization 有時會起到反作用,所以需要關(guān)注!)

  • 優(yōu)先修復(fù)慢渲染,再修復(fù)重新渲染。

  • 把狀態(tài)盡可能地放在它被使用的地方,一方面讓代碼讀起來更順,另一方面,能讓你的 app 更快(state colocation(狀態(tài)托管))

  • Context 應(yīng)該按邏輯分開,不要在一個 provider 中管理多個 value。如果其中某個值變化了,所有使用該 context 的組件(即便沒有用到這個值),都會重新渲染。

  • 可以通過拆分 state 和 dispatch 來優(yōu)化 context。

  • 了解下 lazy loading(懶加載)和 bundle/code splitting(代碼分割)。

  • 長列表請使用 tannerlinsley/react-virtual 或其它類似的庫。

  • 包體積越小,app 越快。你可以使用 source-map-explorer 或者 @next/bundle-analyzer(用于 NextJS) 來進行包體積分析。

  • 關(guān)于表單的庫,推薦使用 react-hook-forms,它在性能和開發(fā)體驗各方面都做的比較好。

  • 🧘 4. 測試原則

  • 測試應(yīng)該始終與軟件的使用方式相似。

  • 確保不是在測試一些邊界細節(jié)(用戶不會使用,看不到甚至感知不到的內(nèi)容)。

  • 如果你的測試不能讓你對自己的代碼產(chǎn)生信任,那測試就是無意義的。

  • 如果你正在重構(gòu)某個代碼,且最后實現(xiàn)的功能都是完全一致的,其實幾乎不需要修改測試,而且可以通過測試結(jié)果來判定你正確的重構(gòu)了。

  • 對于前端來說,不需要 100% 的測試覆蓋率,70% 就足夠了。測試應(yīng)該提升你的開發(fā)效率,雖然維護測試會暫時地阻塞你目前的開發(fā),但當你不斷地增加測試,會在不同階段得到不同的回報。

  • 我個人喜歡使用 Jest,React testing library,Cypress,和 Mock service worker。

  • End

    翻譯的不好,請大家見諒。如有任何想法,歡迎評論交流

    參考資料

    [1]

    https://github.com/mithi/react-philosophies: https://github.com/mithi/react-philosophies

    [2]

    mithi: https://github.com/mithi

    [3]

    【你不需要系列之“你不需要 Lodash/Underscore”】: https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore

    [4]

    【你不需要系列之“你不需要 Momentjs”】: https://github.com/you-dont-need/You-Dont-Need-Momentjs

    [5]

    【你不需要系列之“你不需要 JavaScript”】: https://github.com/you-dont-need/You-Dont-Need-JavaScript

    ·················?若川簡介?·················

    你好,我是若川,畢業(yè)于江西高校。現(xiàn)在是一名前端開發(fā)“工程師”。寫有《學(xué)習(xí)源碼整體架構(gòu)系列》20余篇,在知乎、掘金收獲超百萬閱讀。
    從2014年起,每年都會寫一篇年度總結(jié),已經(jīng)堅持寫了8年,點擊查看年度總結(jié)。
    同時,最近組織了源碼共讀活動,幫助3000+前端人學(xué)會看源碼。公眾號愿景:幫助5年內(nèi)前端人走向前列。

    掃碼加我微信 ruochuan02、拉你進源碼共讀

    今日話題

    略。分享、收藏、點贊、在看我的文章就是對我最大的支持~

    總結(jié)

    以上是生活随笔為你收集整理的一份 2.5k star 的《React 开发思想纲领》的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。