原文地址: (A => B) !=> (B => A)
原文做者: Jim Sproch
譯者: arzh
推薦理由: react官網中推薦的博客,文章能夠幫忙深刻理解componentWillReceiveProps這個屬性,雖然在17版本準備廢棄今生命週期,可是這篇文章對componentWillReceiveProps的理解仍是值得咱們學習的html
componentWillReceiveProps
的文檔聲明,當props
做爲從新渲染的結果發生變化時,將調用componentWillReceiveProps
。有些人認爲這意味着「若是componentWillReceiveProps
被調用,那麼props
必定是已經改變」,但這個結論在邏輯上是不正確的。react
指導原則是我對形式邏輯/數學的最愛之一:網絡
A能推導出B並不意味着B能推導出A數據結構
例如:「若是我吃發黴的食物,我就會生病」並不意味着「若是我生病了,那麼我必定是吃了發黴的食物」。我生病還有許多其餘的緣由。例如,也許流感正在辦公室傳播。相似地,即便props
沒有改變,仍是有不少緣由可使componentWillReceiveProps
被調用。閉包
若是你不相信,用相同的props
調用ReactDOM.render()
三次,試着預測一下componentWillReceiveProps
會被調用多少次函數
在這種狀況下,答案是2
。React
調用componentWillReceiveProps
兩次(每次更新記錄一次)。這兩次,drinks
都被打印出來(componentWillReceiveProps
被調用了),可是props
沒有發生改變。學習
要理解緣由,咱們須要考慮發生了什麼。若是代碼執行了這樣的改動,那麼數據可能在初始呈現和隨後的兩次更新之間發生了更改 code
React
沒法知道數據有沒有發生變化。所以,React
須要調用componentWillReceiveProps
,由於須要通知組件有新的props
(即便新的props
碰巧與舊props
相同)。component
你可能認爲React
可使用更有效的檢查來判斷props
是否全等,可是這個想法存在一些問題:cdn
mydata
和新的mydata
其實是相同的實體對象(只改變了對象的內部值)。因爲引用是triple-equals-equal(===),因此進行相等檢查(==)不會告訴咱們值是否發生了更改。惟一可能的解決方案是建立數據的深度副本,而後進行深度比較——可是對於大型數據結構(特別是具備週期的數據結構),這可能須要的代價特別高。mydata
對象可能包含對函數的引用,這些函數在閉包中捕獲了變量。 React沒法窺視這些閉包,所以React沒法複製它們或者驗證它們的相等性。mydata
對象可能包含在父組件渲染期間從新實例化的對象的引用(即,不是triple-equals-equal(===))但在概念上相等(即,相同的鍵和相同的值)。深度比較(代價昂貴)能夠檢測到這一點,可是函數比較又出現了問題,由於沒有可靠的方法來比較兩個函數以肯定它們在語義上是否等價。因爲語言的限制,咱們有時不可能實現有意義的相等語義。在這種狀況下,React
將調用componentWillReceiveProps
(即便這些props
可能沒有更改),這樣組件就有機會檢查新的props
並採起相應的行動。
所以,componentWillReceiveProps
被調用不能認爲props
已經更改。若是你想要一個操做(例如網絡請求)僅在props
更改時發生,componentWillReceiveProps
代碼須要檢查props
是否實際更改。