反应:新安装的 child 组件无法访问 Parent 组件引用?

React: Parent component refs not accessible to newly mounted child component?

我在做什么:

简单 - 我需要在安装包含消息列表的组件 (Messages) 后立即滚动到消息列表的底部。

我程序中的活动扳手:)

安装后滚动到底部没问题,直到...

我简单地移动了一些家具,将 scroll-able child 组件(Messages)的 header 移到了它的 parent 中component(MessageSection) 为了让 header 坚持。

这是之前和之后:

之前(太棒了!) MessageSection.js

if(this.state.messages !== null) 
  return (
    <ScrollArea speed={0.8} className="area" contentClassName="content">
      <Messages  messages={this.state.messages} />
    </ScrollArea>
  );
}else{

  return (
    <ScrollArea speed={0.8} className="area" contentClassName="content">
      <EmptyMessages />
    </ScrollArea>
  );
}

简单差异:

(基本上只是把Messages的标题移动到parent MessageSection)

  1. 从滚动 child 组件中拉出 header(Messages)。

  2. 将header放在ScrollArea上方

  3. 然后渲染新的 JSX -我将 Header 和 ScrollArea 包裹在一个新的 div ("messages")

之后:(什么!你不工作了??)

MessageSection.js

if(this.state.messages !== null) {
  return (
    <div className="messages">
      <div className ="messages-section-header">
        <span className="header">{this.props.name}</span>
      </div>
      <ScrollArea speed={0.8} className="area scrollarea-flex" contentClassName="content">
        <Messages  messages={this.state.messages} />
      </ScrollArea>
    </div>
  );
}else{
  return (
    <div className="messages">
      <ScrollArea speed={0.8} className="area scrollarea-flex" contentClassName="content">
        <EmptyMessages />
      </ScrollArea>
    </div>
  );
}

错误:

重构后我从 ScrollArea.jsx#L222

得到了这个错误

未捕获类型错误:无法读取 属性 'offsetHeight'


错误原因:

当 scroll-able 组件 Messages 安装在它的 componentDidMount 中时,它会尝试使用 ScrollArea 组件的公开上下文滚动到底部,但是refs里面的ScrollArea是不存在的。这很奇怪,因为如果稍后由 componentDidUpdate

调用,refs 将存在

作为参考,这里是发生故障的 child 组件。

MessageList.js(Scroll-able 安装时尝试滚动到底部的组件)

contextTypes: {
  scrollArea: React.PropTypes.object //Used by the Library to Access the Scrolling Panel(The Parent Component)
},

componentDidMount: function() {
    this._scrollToBottom(); 
},

_scrollToBottom: function() {
    var scrollHeight = this.refs.messages.scrollHeight; 
    this.context.scrollArea.scrollYTo(scrollHeight);//ERROR -the refs will not exist inside context as expected
}

为什么我感到困惑:

没意义ScrollArea怎么挂载,childMessages也可以挂载,调用定义的上下文ScrollArea 暴露给它,但 ScrollArea 的引用不存在??? 这是双重混乱,因为它在我做小改动之前就起作用了。

问题:

我的代码结构中的简单更改怎么会导致上下文无法访问它的引用

父组件只有在其所有子组件 "mounted" 之后才 "mounted"。所以当你的 Message componentDidMount 正在执行时,你的 ScrollArea 仍在 "mounting" 的过程中。

您的问题是您为交互建模的方式造成的:您有一个 "child" 组件指示某些父组件的行为。如果你让你的父组件负责这个滚动行为,那么一切都会起作用。

具体来说,将 componentDidMount 方法添加到您的 MessageSection 组件并将逻辑放在那里:

componentDidMount: function() {
    // Assume you add `ref="messages"` to your render method so you can
    // get a reference to the child component
    this.refs.messages._scrollToBottom();
}