簡體   English   中英

引用安裝/更新組件的生命周期

[英]Refs in mount/update component lifecycle

我有一個無限的滾動列表,可以雙向滾動。 該列表顯示了每行5個項目的網格,該網格代表一周7天中的5個工作日。 斑馬按天剝離斑馬紋(甚至幾個月的顏色略深)。 我想將月份標題放置在網格左側的一列中,從該月的第一天開始,或者該月可用的最早的一天(考慮到數據中的AJAX,但並不總是從第一個工作日開始)的月份)。

我擁有所有必要的邏輯來確定哪一天是第一天(因為我只顯示工作日,如果第一天是周末,那么月初可能不是第一天)。

到目前為止,我有以下內容:

  1. 當渲染網格,吊牌月初和月中的一個最終ref中的格式YYYYMM_startYYYYMM_end
  2. 然后,我使用具有與monthStamp相同格式的YYYYMM以及一個findMonthNode (使用正則表達式)來接收在父組件上查找開始和結束節點的函數來呈現MonthTitle組件。

  3. 然后,在MonthTitle組件的componentDidMount ,可以將標題絕對相對於該月的起始節點定位。 我還調用了componentDidUpdate完全相同的函數。

我的問題是,當我向后滾動列表時(請記住,在兩個方向上都可以無限滾動):我的AJAX會觸發並加載帶有新月份標題的新圖塊,並且新月份標題會適當地呈現,但是是原始的第一個標題不會相應更新。 一些閑逛之后,我意識到, this.refs在父組件componentDidUpdate 不等於 this.refs在父組件componentDidMount componentDidMount似乎具有完整的列表,而componentDidUpdate僅具有在掛載新節點(來自AJAX響應)之前存在的節點的列表。

由於componentDidUpdate並沒有所有新的引用,因此我無法相應地放置先前的第一個月標題,並且它仍然停留在componentDidMount中最初呈現的位置(鑒於新數據)現在是不正確的位置。


為什么this.refs在這兩個函數( componentDidMountcomponentDidUpdate )中this.refs不同? 在安裝和更新組件時,如何確保可以訪問完整的this.refs

使用react 0.13.3 FYI

如果您在此處查看組件生命周期規格,您將看到每次更新componentDidUpdate都會運行componentDidUpdate(通過組件或其祖先之一中的this.setState ),而不是在初始渲染之后運行:

componentDidUpdate(object prevProps, object prevState)

組件的更新刷新到DOM后立即調用。 初始渲染不調用此方法。

另一方面, componentDidMount在初始渲染后運行,但在通過setState更新后不運行:

componentDidMount()

初始渲染發生后立即僅在客戶端(而不是服務器)上調用一次。

因此,如果您更新狀態(通過組件中的this.setState )並重新呈現組件,並有可能添加具有ref屬性的新子元素,則這些子元素將不會在父componentDidMountcomponentDidMount可見,而在componentDidUpdate可見。

另一方面,如果您更新父組件並且更新呈現新的子組件,則這些子組件的componentDidMount實際上會在父組件的componentDidUpdate之前觸發,因為父組件在所有新的子組件均已正確安裝並正確渲染之前尚未完成更新。 它會像這樣:

  1. 任何初始子級的componentDidMount執行(也許有些令人驚訝,但是直到所有子級都掛載后,父級才完成掛載,這是有道理的)
  2. 父母的componentDidMount執行
  3. 父級通過setState更新,其中添加了一些子級,並且某些子級上次渲染已存在
  4. 執行所有新添加的子級的componentDidMount和執行所有以前存在的子級的componentDidUpdate
  5. 父母的componentDidUpdate執行

這是JSFiddle演示的。

好的,我想出了一個解決方案。 我沒有讓MonthTitle在其生命周期回調中處理自己的位置( componentDidMountcomponentDidUpdate ),而是讓其父級組件( Grid )調用標題上的方法以將其放置在父級的componentDidUpdate

因此,大致而言,在Grid ,我具有以下內容:

componentDidUpdate() {
  for (let [ref, component] of entries(this.refs)) {
    if (/_title$/.test(ref)) {
      var startOfMonthNode = React.findDOMNode(findRef("startOfMonth", this.refs, component.props.monthStamp))
      var endOfMonthNode = React.findDOMNode(findRef("endOfMonth", this.refs, component.props.monthStamp))

      component.position(startOfMonthNode, endOfMonthNode)
    }
  }
}

然后,在我的MonthTitle組件中,定義定位邏輯:

position(startOfMonthNode, endOfMonthNode) {
  React.findDOMNode(this).style["top"] = getDimension((startOfMonthNode || endOfMonthNode), "top") + window.scrollY - 116 + "px"
}

這意味着我必須將標題本身添加到Grid refs列表中。


因此,從概念上講, 位置更新從子組件的生命周期到父組件的生命周期發生變化 ,差異就在轉移。 由於父組件的componentDidUpdate將在安裝任何新的子組件后觸發,因此我有完整的refs列表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM