我有一个向两个方向滚动的无限滚动列表。该列表显示每行5个项目,表示7天工作日中的5个工作日。这些日子是按月剥离的斑马(甚至几个月的颜色稍暗)。我想将月份标题放在网格左侧的一列中,从该月的第一天开始,或者该月份可用的最早日期(考虑到AJAXed数据 - 并不总是从第一个工作日开始)当月)。
我已经掌握了所有必要的逻辑,以确定哪一天是第一天(因为我只显示工作日,如果第一天是在周末,那么月初可能不是第一天)。
到目前为止,我有以下内容:
ref
或YYYYMM_start
格式的YYYYMM_end
标记月份的开头和月末。然后,我使用MonthTitle
支柱呈现monthStamp
组件,其格式与YYYYMM
相同,以及findMonthNode
道具接收到函数查找父组件上的开始和结束节点(使用正则表达式)。
在MonthTitle
组件的componentDidMount
中,我可以绝对相对于该月的起始节点定位标题。我还在componentDidUpdate
中调用完全相同的函数。
我的问题是当我滚动列表(请记住,两个方向无限滚动)时间:我的AJAX在新的月份标题中激活并加载新的图块,并且新的月份标题正确呈现,但是第一个原始标题不会相应更新。经过一番探讨后,我意识到this.refs
中父组件中的componentDidUpdate
与父组件中的 this.refs
不相等componentDidMount
。 componentDidMount
似乎有完整的列表,而componentDidUpdate
只有在安装新节点(来自AJAX响应)之前存在的节点列表。
由于componentDidUpdate
没有所有新的引用,我无法相应地定位先前的第一个月标题,并且它仍然停留在最初在componentDidMount
中呈现的位置,其中 - 给定新数据 - 现在是不正确的位置。
为什么this.refs
在这两个函数(componentDidMount
& componentDidUpdate
)中有所不同?我该怎么做才能确保在安装和更新组件时能够访问完整的this.refs
?
使用react 0.13.3
FYI
答案 0 :(得分:3)
如果您查看组件生命周期规范here,您会看到每次更新组件时都会运行componentDidUpdate
(通过组件中的this.setState
或其中一个组件祖先),但不是在初始渲染之后:
另一方面,
componentDidUpdate(object prevProps, object prevState)
在将组件的更新刷新到之后立即调用 DOM。初始渲染不会调用此方法。
componentDidMount
在初始渲染后运行,但不是在通过setState
更新后运行:
componentDidMount()
立即仅在客户端(不在服务器上)调用一次 初始渲染发生后。
因此,如果您更新状态(通过组件中的this.setState
)并重新渲染组件,可能会添加具有ref
属性的新子元素,那么这些元素将不会显示在父级&#中39; s componentDidMount
但在componentDidUpdate
。
另一方面,如果您更新父组件并且更新呈现新的子组件,那么这些子组件会被更新。 componentDidMount
确实将在父componentDidUpdate
之前触发,因为父组件未完成更新,直到其所有新子组件都已正确安装和呈现。它会是这样的:
componentDidMount
执行(或许有点令人惊讶,但父母没有安装,直到所有孩子都装上了,这很有意义)componentDidMount
执行setState
通过一些已添加的子项以及上次呈现已存在的子项componentDidMount
执行以及所有以前存在的儿童' componentDidUpdate
执行componentDidUpdate
执行Here's a JSFiddle证明了这一点。
答案 1 :(得分:0)
好的,我找到了解决方案。在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"
}
组件中,我定义了定位逻辑:
refs
这意味着我必须将标题本身添加到Grid
中的componentDidUpdate
列表中。
因此,从概念上讲,差异在于 时,定位更新从子组件的生命周期发生到父组件的生命周期。由于父组件的refs
将在安装任何新的子组件后触发,因此我有; unit test code
if @ScriptName == "included_script.au3" Then
MsgBox(0,"Unit Test","Running unit test...",3)
test()
exit
endif
func test()
; no test defined
EndFunc
的完整列表。