問題
這篇博客僅作爲學習筆記,沒有多少自己的東西,只有一個小誤區,記錄下來當做備忘。
學習資料:
關於Immutable.js如何整合進React中,推薦閱讀官方的文檔和上面第二篇博客,下面不會說具體的使用方法,所以閱讀到這裏這篇博客算是結束了。
下面說說我以前在setState中踩的坑,同時也回答了一個問題,爲什麼需要Immutable.js這個輪子。
年少時不小心犯下的錯
最近會啓動一個新的項目,在進行技術選型的時候特地看了Immutable.js,才發現自己以前寫碼有些錯誤的地方。
上代碼:
let data = this.state.data;
data.times = data.times + 1;
this.setState({ data: data });
// 下面打印的結果會是已經加 1 後的值。
console.log(this.state.data.times);
還記得該系列的上一篇文章ReactJS修煉之路(四):組件的性能優化及開發思路中提到的shouldComponentUpdate: function(nextProps, nextState)
,因爲上面的操作直接改變了this.state.data
的值,所以在shouldComponentUpdate
中nextState.data
和this.state.data
其實是同一個對象(2016-12-03更新:這裏容易產生誤區,再說得詳細一點,因爲我們在調用this.setState({ data: data })
時,把原來的state中的state賦給了新的state,所以下面的nextState.data
和this.state.data
是同一個對象,既然是同一個對象的兩個不同引用而已,那麼無論怎麼比較得出的結果都是nextState.data
和this.state.data
相同,所以返回false
),因此無論怎麼比較都會返回false
,導致組件不更新。
正確的做法應該如下:
let data = _.cloneDeep(this.state.data);
data.times = data.times + 1;
this.setState({ data: data });
// 如果上面不做 cloneDeep,下面打印的結果會是已經加 1 後的值。
console.log(this.state.data.times);
這樣的話,沒有改變this.state.data
的值,通過調用setState
,使得在shouldComponentUpdate
中nextState.data
是新的值,可以與this.state.data
比較,根據比較結果判斷是否更新組件。
那麼爲什麼需要Immutable.js?
let data = _.cloneDeep(this.state.data);
這行代碼可以看出,爲了新建一個對象,我們在原對象的基礎上進行了深度拷貝,然後改變新對象的值,深度拷貝的壞處很明顯,對象越複雜,性能開銷越大,而Immutable.js能通過不可變對象來避免這個問題,具體原理看上面的學習資料可以求解:
else
有一段時間沒更新博客了,跟國慶假期有關,但主要原因還是遇到的問題少了,倒不是說自己水平提升了很多,而是自己實際編碼的時間少了(話說最近看了《易中天中華史》,十分推薦)。
只有coding能產生問題,也只有coding能解決問題,提升自己。
加油。