[譯](A => B) !=> (B => A)

原文地址: (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會被調用多少次函數

在這種狀況下,答案是2React調用componentWillReceiveProps兩次(每次更新記錄一次)。這兩次,drinks都被打印出來(componentWillReceiveProps被調用了),可是props沒有發生改變。學習

要理解緣由,咱們須要考慮發生了什麼。若是代碼執行了這樣的改動,那麼數據可能在初始呈現和隨後的兩次更新之間發生了更改 code

React沒法知道數據有沒有發生變化。所以,React須要調用componentWillReceiveProps,由於須要通知組件有新的props(即便新的props碰巧與舊props相同)。component

你可能認爲React可使用更有效的檢查來判斷props是否全等,可是這個想法存在一些問題:cdn

  1. 舊的mydata和新的mydata其實是相同的實體對象(只改變了對象的內部值)。因爲引用是triple-equals-equal(===),因此進行相等檢查(==)不會告訴咱們值是否發生了更改。惟一可能的解決方案是建立數據的深度副本,而後進行深度比較——可是對於大型數據結構(特別是具備週期的數據結構),這可能須要的代價特別高。
  2. mydata對象可能包含對函數的引用,這些函數在閉包中捕獲了變量。 React沒法窺視這些閉包,所以React沒法複製它們或者驗證它們的相等性。
  3. mydata對象可能包含在父組件渲染期間從新實例化的對象的引用(即,不是triple-equals-equal(===))但在概念上相等(即,相同的鍵和相同的值)。深度比較(代價昂貴)能夠檢測到這一點,可是函數比較又出現了問題,由於沒有可靠的方法來比較兩個函數以肯定它們在語義上是否等價。

因爲語言的限制,咱們有時不可能實現有意義的相等語義。在這種狀況下,React將調用componentWillReceiveProps(即便這些props可能沒有更改),這樣組件就有機會檢查新的props並採起相應的行動。

所以,componentWillReceiveProps被調用不能認爲props已經更改。若是你想要一個操做(例如網絡請求)僅在props更改時發生,componentWillReceiveProps代碼須要檢查props是否實際更改。

相關文章
相關標籤/搜索