React:获取组件的其中一个子组件的 DOM 位置

IT技术 javascript reactjs
2021-05-03 10:32:29

我有一个非常烦人的问题,我需要有关我的组件的帮助。它在这样的上下文中使用:

<table>
  <thead>/* ... */</thead>
  <tbody>
    <COMPONENT>
      <ChildComponent>/* ... */</ChildComponent>
      <ChildComponent>/* ... */</ChildComponent>
      <ChildComponent>/* ... */</ChildComponent>
    </COMPONENT>
  </tbody>
</table>

ChildComponent是一个包含其他组件但最终呈现简单 HTML 的组件<tr>

component.tsx 中,我需要为第 n 个孩子获取 DOM 值(offsetTop 和 clientHeight)。

我尝试了很多事情:

  • ReactDOM.findDOMNode(children[n]) 给我:

参数似乎不是 ReactComponent。键:$$typeof, type, key, ref, props, _owner, _store

  • children[n].ref 只是给我空
  • 不能向孩子添加引用
  • 这类作品:
children.map((child, index) =>
    index === n ? (
        <div style={{display: contents}} key={index} ref={ref}>
    ) : child
)

给我警告(但有效!):

index.js:2178 警告:validateDOMNesting(...): 不能作为 . 在 tr(由 FoldControlContainer 创建)...

有更好的解决方案吗?我尝试使用 <> 或其他“透明”的 DOM 组件而不是div,但它没有用。

2个回答

使用 React.cloneElement 为孩子设置参考:https : //reactjs.org/docs/react-api.html#cloneelement ex:

React.cloneElement(child, {ref: this.setChildRef})}
export default class Test extends React.Component {

  childrenRefs = {}

  setChildRef = index => el => this.childrenRefs[index] = el;

  showInfo = () => {
    console.log('children', Object.keys(this.childrenRefs).map(key => this.childrenRefs[key].offsetTop))
  }

  render() {

    return (
      <div>
        { React.Children.toArray(this.props.children).map((c, index) => React.cloneElement(
          c,
          {ref: this.setChildRef(index)},
        ))}
        <button onClick={this.showInfo} >test</button>
      </div>
    );
  }
} 

这是一个完整工作示例的链接:https : //stackblitz.com/edit/react-cf33ge 打开右下角的控制台以查看输出。

findDOMNode期望 的实例React.Component组件应该使用 refs 呈现以获取实例。由于 refs 不在<ChildComponent>/* ... */</ChildComponent>儿童中使用,因此应该使用 ref 克隆它们。

如果子组件应该是类组件元素并且它们的数量在父组件生命周期内不会改变,则情况可以简化为:

childRefs = [...Array(React.Children.count(this.props.children))]
.map(() => React.createRef());

render() {
  return React.Children.map(this.props.children, ((child, i) => 
    React.cloneElement(child, { ref: this.childRefs[i] });
  )
}

DOM 元素ReactDOM.findDOMNode(this.childRefs[n].current)在组件安装时可用