原文永久連接: https://github.com/AttemptWeb.....javascript
下面說到的React開發中注意的問題,部分是本身遇到過的點,部分是收集的,也算是React代碼優化部分,此次作一個整理,但願能夠幫助到你html
當組件的props 或者 state 改變時,可能會出現重複setState的狀況,對於重複的操做,咱們能夠經過下面的方法來避免重複渲染:java
shouldComponentUpdate 返回true,確認真實DOM須要改變時,返回true。通常的作法是比較組件的props和state是否真的發生變化,若是發生變化則返回true,不然返回false。react
shouldComponentUpdate(nextProps, nextState) { if (this.props.id !== nextProps.id) { return true; } if (this.state.type !== nextState.type) { return true; } return false; }
React文檔:shouldComponentUpdate()git
React文檔:shouldComponentUpdate 的做用github
React.PureComponent,沒必要寫你本身的shouldComponentUpdate,它提供了一個淺比較。若是對象中包含複雜的數據結構,則有可能由於沒法檢查深層的差異,產生錯誤的比對結果。在你的 props 和 state 較爲簡單時,可使用 React.PureComponent。(補充:當你比較的目標爲引用類型數據,淺比較會忽略屬性或狀態)api
class ChildComponent extends React.PureComponent { render() { return( <>{this.state.type}</> ) } }
不可變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,目前我尚未在項目中嘗試過,內容來源於社區,若是有相關文章,能夠推薦給我。函數
key 幫助React識別哪些元素改變了,好比被添加或刪除。所以你應當給數組中的每個元素賦予一個肯定的標識。對於列表組件,key 最好是這個元素在列表中擁有的一個獨一無二的字符串。
listData.map((item) => <li key={item.id}> {item.text} </li> );
列表組件 Diff比對時,使用元素在數組中的下標做爲 key,列表順序發生修改,就表明原來的React節點組件沒法複用,須建立新的React.Element節點,這樣diff 會變得慢。
當基於下標的組件進行從新排序時,組件基於它們的 key 來決定是否更新以及複用,若是 key 是一個下標,那麼修改順序時會修改當前的 key,致使組件的 state(好比輸入框)可能相互篡改致使沒法預期的變更。
虛擬列表是常見的‘長列表'和'複雜組件樹'優化方式,它優化的本質就是減小渲染的節點。只渲染當前視口可見元素。
虛擬列表適用場景:無限滾動列表, 表格,下拉列表,大數據量或無限嵌套的樹等。
相關組件方案:
react-virtualized react-window
隨着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的比較。默認狀況下其只會對複雜對象作淺層對比,若是你想要控制對比過程,那麼請將自定義的比較函數經過第二個參數傳入來實現。
不管是 props和state 儘可能只傳須要的數據,避免多餘的更新。對於項目的後期維護特別重要。(我已經踩坑了。。。)
<ListInfoCard data={...state}>
列表組件、表單組件、商品卡片、icon組件,儘可能作到適度的拆分,業務組件和展現組件的分離,易於後期的維護和迭代,同時也能夠提高性能。在平時開發中,對於一個單獨的頁面,數據量不大,直接將業務和展現組件捆綁在一塊兒,在初期,這個是無關痛癢的,若是是一次性開發,問題也不是特別大,可是一旦去要後期的迭代優化,就有問題了。
本身遇到開發方面的問題基本就這些了,上面提到的基本都是我遇到過的和研究過的,但願能夠幫助到你。這些只是React項目代碼層面的東西,若是你須要作一些優化方面的工做,也能夠從打包、編譯入手。
ps: 順便推一下本身的我的公衆號:Yopai,有興趣的能夠關注,每週不按期更新,分享能夠增長世界的快樂