如何在React中调用所有子组件的函数

3

这是我尝试的。文档似乎表明 this.props.children 是由React管理的特殊属性,但在此示例中children为未定义。我做错了什么?

class Child extends React.Component {
  render() {
    return React.createElement('div', {}, this.props.content);
  }     
  someFunc() {
    log("child", this.props.content);
  }
}
           
class Parent extends React.Component {
  render() {
    return React.createElement('div', {ref: 'self'}, 
      React.createElement(Child, {content: "child A"}, null),
      React.createElement(Child, {content: "child B"}, null),
      React.createElement(Child, {content: "child C"}, null)
    );
  }
  componentDidMount() {
    console.log("children:", this.props.children);      
    React.Children.forEach(this.props.children, (child) => {
      log("child");
      child.someFunc();
    });
  }
}
            
ReactDOM.render(<Parent />, document.getElementById("react"));

function log(...args) {
  const elem = document.createElement("pre");
  elem.textContent = [...args].join(" ");
  document.getElementById("log").appendChild(elem);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="react"></div>
<div id="log"></div>

我需要解决的问题是,我有一个Windows Explorer类似的界面,左侧有组名,右侧有所有组中项的列表。当我点击左侧的组名时,我希望滚动右侧的列表以显示相应的项目。请注意,左侧的组与右侧的项之间没有内部连接。它们只是相同数据的两个表示。为了实现我的目标,在左侧单击元素时,我希望在右侧找到该元素并询问DOM它在哪里,以便设置滚动偏移量。我有足够的信息在右侧找到该元素,但是当我尝试使用this.props.children遍历它们时,发现它是未定义的。
请注意,在我的实际代码中,我没有在componentDidMount 中运行此代码,而是在鼠标单击的响应中调用此代码。
因此,我的第一次解决方法是,向所有子代传递EventEmitter,然后发出事件。可以通过props传递一个registerYourselfWithParent函数,但这也需要一个unregisterYourselfWithParent。我猜两种方法都可以。

你不能通过 this.props.children 访问到你的组件的子元素。this.props.children 表示由父组件传递给你的子元素,而不是在 render() 中创建的子元素。换句话说,渲染 ReactDOM.render(<Parent><Child content="TEST"></Parent>, document.getElementById("react")); 将会记录具有内容 "TEST" 的子元素。 - nem035
1个回答

3

动态为您的子组件分配引用,例如React.createElement(Child, {content: "child A", ref:getRef()}, null),其中getRef是一个函数。

var getRef = function(){ return 'Child-'+(refi++); }

然后使用Object.keys(this.refs).forEach()循环引用。

componentDidMount() {

    Object.keys(this.refs).forEach( (child) => {
      if(child !== 'self') {
      console.log(child);
      this.refs[child].someFunc();
       }
    });
  }

class Child extends React.Component {
  render() {
    return React.createElement('div', {}, this.props.content);
  }     
  someFunc() {
    console.log("child", this.props.content);
  }
}
           
class Parent extends React.Component {
  
  render() {
    var getRef = function(){ return 'Child-'+(refi++); },    refi=0;
   
    return React.createElement('div', {ref: 'self'}, 
      React.createElement(Child, {content: "child A", ref:getRef()}, null),
      React.createElement(Child, {content: "child B", ref: getRef()}, null),
      React.createElement(Child, {content: "child C", ref:getRef()}, null)
    );
  }
  componentDidMount() {
          
    Object.keys(this.refs).forEach( (child) => {
      if(child !== 'self') {
      console.log(child);
      this.refs[child].someFunc();
       }
    });
  }
}
            
ReactDOM.render(<Parent />, document.getElementById("react"));

function log(...args) {
  const elem = document.createElement("pre");
  elem.textContent = [...args].join(" ");
  document.getElementById("log").appendChild(elem);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="react"></div>
<div id="log"></div>

希望这能对您的事业有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接