有什么方法可以访问嵌套在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对象以调用属于特定孩子的方法?
先谢谢了。
答案 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):
何时使用参考:
避免将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} />);