繁体   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