参考安装/更新组件生命周期

时间:2015-07-13 17:01:42

标签: javascript reactjs

我有一个向两个方向滚动的无限滚动列表。该列表显示每行5个项目,表示7天工作日中的5个工作日。这些日子是按月剥离的斑马(甚至几个月的颜色稍暗)。我想将月份标题放在网格左侧的一列中,从该月的第一天开始,或者该月份可用的最早日期(考虑到AJAXed数据 - 并不总是从第一个工作日开始)当月)。

我已经掌握了所有必要的逻辑,以确定哪一天是第一天(因为我只显示工作日,如果第一天是在周末,那么月初可能不是第一天)。

到目前为止,我有以下内容:

  1. 在渲染网格时,使用refYYYYMM_start格式的YYYYMM_end标记月份的开头和月末。
  2. 然后,我使用MonthTitle支柱呈现monthStamp组件,其格式与YYYYMM相同,以及findMonthNode道具接收到函数查找父组件上的开始和结束节点(使用正则表达式)。

  3. MonthTitle组件的componentDidMount中,我可以绝对相对于该月的起始节点定位标题。我还在componentDidUpdate中调用完全相同的函数。

  4. 我的问题是当我滚动列表(请记住,两个方向无限滚动)时间:我的AJAX在新的月份标题中激活并加载新的图块,并且新的月份标题正确呈现,但是第一个原始标题不会相应更新。经过一番探讨后,我意识到this.refs 中父组件中的componentDidUpdate与父组件中的 this.refs不相等componentDidMountcomponentDidMount似乎有完整的列表,而componentDidUpdate只有在安装新节点(来自AJAX响应)之前存在的节点列表。

    由于componentDidUpdate没有所有新的引用,我无法相应地定位先前的第一个月标题,并且它仍然停留在最初在componentDidMount中呈现的位置,其中 - 给定新数据 - 现在是不正确的位置。

    为什么this.refs在这两个函数(componentDidMount& componentDidUpdate)中有所不同?我该怎么做才能确保在安装和更新组件时能够访问完整的this.refs

    使用react 0.13.3 FYI

2 个答案:

答案 0 :(得分:3)

如果您查看组件生命周期规范here,您会看到每次更新组件时都会运行componentDidUpdate(通过组件中的this.setState或其中一个组件祖先),但不是在初始渲染之后:

  

componentDidUpdate(object prevProps, object prevState)

     

在将组件的更新刷新到之后立即调用   DOM。初始渲染不会调用此方法。

另一方面,

componentDidMount在初始渲染后运行,但不是在通过setState更新后运行:

  

componentDidMount()

     

立即仅在客户端(不在服务器上)调用一次   初始渲染发生后。

因此,如果您更新状态(通过组件中的this.setState)并重新渲染组件,可能会添加具有ref属性的新子元素,那么这些元素将不会显示在父级&#中39; s componentDidMount但在componentDidUpdate

另一方面,如果您更新父组件并且更新呈现新的子组件,那么这些子组件会被更新。 componentDidMount确实将在父componentDidUpdate之前触发,因为父组件未完成更新,直到其所有新子组件都已正确安装和呈现。它会是这样的:

  1. 任何初始儿童' componentDidMount执行(或许有点令人惊讶,但父母没有安装,直到所有孩子都装上了,这很有意义)
  2. 家长componentDidMount执行
  3. 通过setState通过一些已添加的子项以及上次呈现已存在的子项
  4. 的父级更新
  5. 所有新添加的儿童' componentDidMount执行以及所有以前存在的儿童' componentDidUpdate执行
  6. 家长componentDidUpdate执行
  7. Here's a JSFiddle证明了这一点。

答案 1 :(得分:0)

好的,我找到了解决方案。在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" } 组件中,我定义了定位逻辑:

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 的完整列表。