[英]Refs in mount/update component lifecycle
我有一個無限的滾動列表,可以雙向滾動。 該列表顯示了每行5個項目的網格,該網格代表一周7天中的5個工作日。 斑馬按天剝離斑馬紋(甚至幾個月的顏色略深)。 我想將月份標題放置在網格左側的一列中,從該月的第一天開始,或者該月可用的最早的一天(考慮到數據中的AJAX,但並不總是從第一個工作日開始)的月份)。
我擁有所有必要的邏輯來確定哪一天是第一天(因為我只顯示工作日,如果第一天是周末,那么月初可能不是第一天)。
到目前為止,我有以下內容:
ref
中的格式YYYYMM_start
或YYYYMM_end
。 然后,我使用具有與monthStamp
相同格式的YYYYMM
以及一個findMonthNode
(使用正則表達式)來接收在父組件上查找開始和結束節點的函數來呈現MonthTitle
組件。
然后,在MonthTitle
組件的componentDidMount
,可以將標題絕對相對於該月的起始節點定位。 我還調用了componentDidUpdate
完全相同的函數。
我的問題是,當我向后滾動列表時(請記住,在兩個方向上都可以無限滾動):我的AJAX會觸發並加載帶有新月份標題的新圖塊,並且新月份標題會適當地呈現,但是是原始的第一個標題不會相應更新。 一些閑逛之后,我意識到, this.refs
在父組件componentDidUpdate
不等於 this.refs
在父組件componentDidMount
。 componentDidMount
似乎具有完整的列表,而componentDidUpdate
僅具有在掛載新節點(來自AJAX響應)之前存在的節點的列表。
由於componentDidUpdate
並沒有所有新的引用,因此我無法相應地放置先前的第一個月標題,並且它仍然停留在componentDidMount
中最初呈現的位置(鑒於新數據)現在是不正確的位置。
為什么this.refs
在這兩個函數( componentDidMount
和componentDidUpdate
)中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
屬性的新子元素,則這些子元素將不會在父componentDidMount
的componentDidMount
可見,而在componentDidUpdate
可見。
另一方面,如果您更新父組件並且更新呈現新的子組件,則這些子組件的componentDidMount
實際上會在父組件的componentDidUpdate
之前觸發,因為父組件在所有新的子組件均已正確安裝並正確渲染之前尚未完成更新。 它會像這樣:
componentDidMount
執行(也許有些令人驚訝,但是直到所有子級都掛載后,父級才完成掛載,這是有道理的) componentDidMount
執行 setState
更新,其中添加了一些子級,並且某些子級上次渲染已存在 componentDidMount
和執行所有以前存在的子級的componentDidUpdate
componentDidUpdate
執行 這是JSFiddle演示的。
好的,我想出了一個解決方案。 我沒有讓MonthTitle
在其生命周期回調中處理自己的位置( componentDidMount
和componentDidUpdate
),而是讓其父級組件( 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.