反应:获取嵌套组件

时间:2018-06-25 21:32:29

标签: reactjs

有什么方法可以访问嵌套在react类组件中的子组件?我知道React.children可以让您访问组件的子级,但是我的理解是,如果在render方法中实例化了这些子级,那么这将不起作用。例如,假设您具有以下React类组件:

class Child extends React.Component {
  sayHi(){console.log('child ' + this.props.id + ' says hi')}

  render() {
    return <h1>ID: {this.props.id}</h1>;
  }
}

class Parent extends React.Component {
  render() {
    return <div>
      <Child id="A" />
      <Child id="B" />
      <Child id="C" />
    </div>
  }
}

如果实例化一个新的Parent对象,是否有任何方法可以访问其中的Child对象以调用属于特定孩子的方法?

先谢谢了。

2 个答案:

答案 0 :(得分:1)

您将使用React refs创建和存储对子组件的引用。这些引用具有普通DOM元素的所有方法,此外,您可以在创建它们的React组件类上调用任何公共方法。

class Child extends React.Component {

  sayHi() {
    console.log('child ' + this.props.id + ' says hi')
  }

  render() {
    return <h1>ID: {this.props.id}</h1>;
  }
}

class Parent extends React.Component {
  constructor(props) {
    this.child_1 = React.createRef();

    this.some_event_did_happen = this.some_event_did_happen.bind(this);
  }

  some_event_did_happen() {
    if (this.child_1) {
      this.child_1.sayHi();
    }
  }

  render() {
    return <div>
      <Child id="A" ref={this.child_1} />
      <Child id="B" />
      <Child id="C" />
    </div>
  }
}

请注意,我提倡为此目的使用React引用。最好传递一个EventEmitter,然后使用常规的React状态管理方法来更改您的应用程序状态。但是,React refs是快速解决方案。

答案 1 :(得分:1)

这是绝对可能的(请检查此codesandbox),但我们应该确保需要这种模式,这是当我们真正应该使用父对象上的ref来控制子组件时,react doc可悲的一面: link to the docs):

何时使用参考

  • 管理焦点,文本选择或媒体播放。
  • 触发命令性动画。
  • 与第三方DOM库集成。
  

避免将refs用于可以声明式完成的任何事情。

     

例如,与其将open()和close()方法暴露在   对话框组件,将isOpen属性传递给它。

下面是使用方法的示例:

父组件:

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

const childrenData = [
  {
    name: 'child 1',
    ref: createRef(),
  },
  {
    name: 'child 2',
    ref: createRef(),
  },
  {
    name: 'child 3',
    ref: createRef(),
  },
];

class Parent extends Component {
  componentDidMount() {
    const [{ ref: firstChildRef }] = childrenData;
    firstChildRef.current.toggle();
  }
  render() {
    return childrenData.map((props) => <Child key={props.name} {...props} />);
  }
}

export default Parent;

子组件:

import React, { Component, forwardRef } from 'react';

const childStyle = {
  border: '2px solid gray',
  padding: 5,
  margin: 5,
};

class Child extends Component {
  state = { enabled: true };

  toggle = () => {
    setTimeout(() => {
      this.setState(({ enabled }) => ({
        enabled: !enabled,
      }));
    }, 500);
  };

  render() {
    const { enabled } = this.state;
    const background = enabled ? 'lime' : 'red';
    return (
      <div style={{ ...childStyle, background }}>
        <h3>{this.props.name}</h3>
        state {enabled ? 'enabled' : 'desabled'}
      </div>
    );
  }
}

export default forwardRef((props, ref) => <Child ref={ref} {...props} />);