聊一聊,React開發中應該規避的點


原文永久鏈接: https://github.com/AttemptWeb.....

下面說到的React開發中注意的問題,部分是自己遇到過的點,部分是收集的,也算是React代碼優化部分,這次做一個整理,希望可以幫助到你

#避免重復渲染

當組件的props 或者 state 改變時,可能會出現重復setState的情況,對於重復的操作,我們可以通過下面的方法來避免重復渲染:

#shouldComponentUpdate

shouldComponentUpdate 返回true,確認真實DOM需要改變時,返回true。一般的做法是比較組件的props和state是否真的發生變化,如果發生變化則返回true,否則返回false。

shouldComponentUpdate(nextProps, nextState) { if (this.props.id !== nextProps.id) { return true; } if (this.state.type !== nextState.type) { return true; } return false; } 

React文檔:shouldComponentUpdate()

React文檔:shouldComponentUpdate 的作用

#React.PureComponent

React.PureComponent,不必寫你自己的shouldComponentUpdate,它提供了一個淺比較。如果對象中包含復雜的數據結構,則有可能因為無法檢查深層的差別,產生錯誤的比對結果。在你的 props 和 state 較為簡單時,可以使用 React.PureComponent。(補充:當你比較的目標為引用類型數據,淺比較會忽略屬性或狀態)

class ChildComponent extends React.PureComponent { render() { return( <>{this.state.type}</> ) } } 

React文檔:React.PureComponent

#不可變Immutable

不可變Immutable,Immutable Data 就是一旦創建,就不能再被更改的數據。對 Immutable 對象的任何修改或添加刪除操作都會返回一個新的 Immutable 對象。更多詳情:Immutable 詳解及 React 中實踐

import { Map, is } from 'immutable'; constructor() { this.state = { // 創建 不可變Immutable data: Map({ times: 0 }) } } shouldComponentUpdate(nextProps, nextState) { for (const key in nextState) { // 通過 is 或者 !== 來比對 if (this.state[key] !== nextState[key] && !is(this.state[key], nextState[key])) { return true; } } } handleAdd() { // 一個全新的對象 const newData = this.state.data.update('times', v => v + 1); this.setState({ data: newData); } 

不可變Immutable,目前我還沒有在項目中嘗試過,內容來源於社區,如果有相關文章,可以推薦給我。

Immutable 詳解及 React 中實踐

#組件優化

#React的key標識

key 幫助React識別哪些元素改變了,比如被添加或刪除。因此你應當給數組中的每一個元素賦予一個確定的標識。對於列表組件,key 最好是這個元素在列表中擁有的一個獨一無二的字符串。

listData.map((item) => <li key={item.id}> {item.text} </li> ); 

列表組件 Diff比對時,使用元素在數組中的下標作為 key,列表順序發生修改,就代表原來的React節點組件無法復用,須創建新的React.Element節點,這樣diff 會變得慢。

當基於下標的組件進行重新排序時,組件基於它們的 key 來決定是否更新以及復用,如果 key 是一個下標,那么修改順序時會修改當前的 key,導致組件的 state(比如輸入框)可能相互篡改導致無法預期的變動。

React文檔:key

#虛擬化長列表

虛擬列表是常見的‘長列表'和'復雜組件樹'優化方式,它優化的本質就是減少渲染的節點。只渲染當前視口可見元素。

虛擬列表適用場景:無限滾動列表, 表格,下拉列表,大數據量或無限嵌套的樹等。

相關組件方案:

react-virtualized react-window

React文檔:虛擬化長列表

#React.memo

隨着React的版本不斷升級,函數式組件功能越來越強大,這也符合它的最初提倡的UI = fn(e)。隨着Hooks、memo的支持,函數組件已非常的成熟。

React.memo為高階組件,可以使用它替換現有的函數組件。它與 React.PureComponent 非常相似,但它適用於函數組件,但不適用於 class 組件。

function areEqual(prevProps, nextProps) { /* 如果把 nextProps 傳入 render 方法的返回結果與 將 prevProps 傳入 render 方法的返回結果一致則返回 true, 否則返回 false */ } function Component(props) { } React.memo(Component, areEqual) 

第一個參數是函數組件,第二個參數非必須,主要是props的比較。默認情況下其只會對復雜對象做淺層對比,如果你想要控制對比過程,那么請將自定義的比較函數通過第二個參數傳入來實現。

React文檔:React.memo

#不濫用props和state

不論是 props和state 盡量只傳需要的數據,避免多余的更新。對於項目的后期維護特別重要。(我已經踩坑了。。。)

<ListInfoCard data={...state}> 

#拆分組件

列表組件、表單組件、商品卡片、icon組件,盡量做到適度的拆分,業務組件和展示組件的分離,易於后期的維護和迭代,同時也可以提升性能。在平時開發中,對於一個單獨的頁面,數據量不大,直接將業務和展示組件捆綁在一起,在初期,這個是無關痛癢的,如果是一次性開發,問題也不是特別大,但是一旦去要后期的迭代優化,就有問題了。

從性能角度看react組件拆分的重要性

#結束

自己遇到開發方面的問題基本就這些了,上面提到的基本都是我遇到過的和研究過的,希望可以幫助到你。這些只是React項目代碼層面的東西,如果你需要做一些優化方面的工作,也可以從打包、編譯入手。

ps: 順便推一下自己的個人公眾號:Yopai,有興趣的可以關注,每周不定期更新,分享可以增加世界的快樂

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM