詳解React中的不可變值
什麼是不可變值
函數式編程是指程序裡面的函數和表達式都能像數學中的函數一樣,給定瞭輸入值,輸出是確定的。比如
let a = 1; let b = a + 1; => a = 1 b = 2;
變量b出現,雖然使用瞭變量a的值,但是沒有修改a的值。
再看我們熟悉的react中的代碼,假如初始化瞭this.state = { count: 1 }
componentDidMount() { const newState = { ...state, count: 2 }; // { count: 2 } this.setState(newState); }
雖然我們使用瞭this.state,但是沒有修改this.state的引用地址和直接修改count的值,對待this.props也一樣。
為什麼使用不可變值
React官網中給出三點好處:
- 簡化復雜的功能
不可變性使得復雜的特性更容易實現。
- 跟蹤數據的改變
如果直接修改數據,那麼就很難跟蹤到數據的改變。跟蹤數據的改變需要可變對象可以與改變之前的版本進行對比,這樣整個對象樹都需要被遍歷一次。
跟蹤不可變數據的變化相對來說就容易多瞭。如果發現對象變成瞭一個新對象,那麼我們就可以說對象發生改變瞭。
- 確定在 React 中何時重新渲染
不可變性最主要的優勢在於它可以幫助我們在 React 中創建 pure components。我們可以很輕松的確定不可變數據是否發生瞭改變,從而確定何時對組件進行重新渲染。
React性能優化離不開不可變值
- 首先,我們都知道,shouldComponentUpdate鉤子函數默認返回true,即隻要父組件更新,子組件一定更新。
- shouldComponentUdpate中可以接收兩個參數,nextProps和nextState,假如我們通過判斷this.props.xxx和nextProps.xxx相等以及this.state.xxx與nextState.xxx相等,可以將返回值設置為false,說明此次並不需要更新子組件。
class CounterButton extends React.Component { constructor(props) { super(props); this.state = {count: 1}; } shouldComponentUpdate(nextProps, nextState) { if (this.props.color !== nextProps.color) { return true; } if (this.state.count !== nextState.count) { return true; } return false; } render() { return ( <button color={this.props.color} onClick={() => this.setState(state => ({count: state.count + 1}))}> Count: {this.state.count} </button> ); } }
- React v15.3新增加瞭一個PureComponent類,能夠對props和state進行淺比較來減少render函數的執行次數,避免不必要的組件渲染,實現性能上的優化。
- PureComponent是什麼原理呢
我們知道JS中的變量類型分為基本類型(number、string、boolean、undefined、null、symbol)和引用類型(function、object、function),基本類型的值保存在棧內存當中,引用類型的值保存在堆內存當中,棧內存中隻保存指向堆內存的引用。而淺比較就是隻對棧內存中的數據進行比較。
class App extends PureComponent { state = { items: [1, 2, 3] } handleClick = () => { const { items } = this.state; items.pop(); this.setState({ items }); } render() { return ( <div> <ul> {this.state.items.map(i => <li key={i}>{i}</li>)} </ul> <button onClick={this.handleClick}>delete</button> </div> ) } }
上邊這個例子使用瞭PureComponent,而且隻改變瞭數組items裡的值,而沒改變items的引用地址,所以認為items沒有發生變化,不會觸發render函數,不會觸發組件的渲染。
如果想實現組件更新,可以按如下的方式,創建一個新的數組,將新數組的地址賦給items。
handleClick = () => { const { items } = this.state; items.pop(); var newItem = [...items]; this.setState({ item: newItem }); }
- PureComponent幫我們做瞭淺層的比較,所以要註意state時盡量合理,如果需要出現引用嵌套引用的數據結構的話,可以配合Immutable.js。
- 什麼是Immutable
(1) Immutable是一旦創建,就不能被更改的數據。(2) 對Immutable對象的任何修改或添加刪除操作都會返回一個新的Immutable對象。(3)Immutable實現的原理是Persistent Data Structure(持久化數據結構),也就是是永久數據創建新數據時,要保證舊數據同時可用且不變。(4)同時為瞭避免deepCopy把所有節點都復制一遍帶來的性能損耗,Immutable使用瞭Structural Sharing(結構共享),即如果對象樹結點發生變化,隻修改這個結點和受它影響的父節點,其他結點進行共享。
最後,如果想要在組件層面進行淺比較,可以使用React.memo()函數
總結
其實還是官網說的不可變性的第三條優勢,也是最主要的優勢,就是不可變性可以幫助我們在React中使用PureComponent。我們可以很輕松的確定數據是否發生瞭改變,組件何時需要發生重新渲染。
如果我們改變瞭state的值,shouldComponentUpdate獲取到當前state和nextState,或者props和nextProps比較出來的值都是完全一樣的,都會返回false,即使我們做瞭setState的操作,UI也不會發生更新。
PureComponent最好是搭配Immutable.js進行使用,來達到性能優化的目的。
結合React.memo來避免沒必要的組件的更新渲染。
以上就是詳解React中的不可變值的詳細內容,更多關於React中的不可變值的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- None Found