首页 > 解决方案 > 在子挂载上访问子组件中的父 Ref

问题描述

我有以下父/子组件。最初呈现 Child 组件后,我需要滚动到顶部。

import React, {Component} from 'react';
import Child from "./Child";

class Parent extends Component {

  render() {
    return (
      <div>
        <div ref={topDiv => {
          this.topDiv = topDiv;
        }}/>
        <Child
          topDiv={this.topDiv}
        />
      </div>
    );
  }
}

export default Parent;
import React, {Component} from 'react';

class Child extends Component {

  componentDidMount() {
    this.scrollToTop();
  }

  // componentWillReceiveProps(nextProps, nextContext) {
  //   nextProps.topDiv.scrollIntoView();
  // }

  scrollToTop() {
    this.props.topDiv.scrollIntoView();
  }

  render() {
    return (
      <div style={{height: '500rem'}}>
        Long Child
      </div>
    );
  }
}

export default Child;

使用它,我得到错误:

TypeError:无法读取未定义的属性“scrollIntoView”

我认为这是因为当componentDidMount被调用时,尚未收到道具,所以topDiv是 null/undefined。

如果我componentWillReceiveProps按照注释部分所示使用,它可以正常工作。但我不能使用它,因为:
1. 它已被弃用。
2.我觉得每次收到道具都会调用。所以我想我需要保留一个变量来知道这是否是第一次收到道具?

我不能使用componentDidUpdate,因为文档说“初始渲染不调用此方法。 ”。

组件渲染后第一次收到 props 怎么办?

标签: javascriptreactjs

解决方案


道具肯定应该在componentDidMount.

这似乎源于 React 生命周期中的一些混乱。

在您的父母中,您大约在您安装的同时在渲染中提供 ref 回调Child。根据反应文档

React 会在组件挂载时使用 DOM 元素调用 ref 回调,并在组件卸载时使用 null 调用它。在 componentDidMount 或 componentDidUpdate 触发之前,保证 Refs 是最新的。

但是,componentDidMountof 孩子会在他们的父母之前触发componentDidMount,所以这个保证并不意味着Parent'sthis.topDiv将在Child调用之前定义componentDidMount。(而且,进一步考虑,它绝对不能保证它会在Child作为道具提供之前被定义。)

在你的父母中,你可以尝试类似的东西

componentDidMount() {
    this.setState({ divSet: true });
}

render() {
    let child = null;
    if (this.state.divSet) {
        child = <Child topDiv={this.topDiv} />
    }

    return (
      <div>
        <div ref={topDiv => {
          this.topDiv = topDiv;
        }}/>
        {child}
      </div>
    );
  }

这将保证您的 ref 在Child安装之前设置。setState专门用于在设置 ref 时强制父级重新渲染。


推荐阅读