最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React: get DOM position for one of the children of component - Stack Overflow

programmeradmin4浏览0评论

I have a very annoying issue, and I need help with my ponent. It is used in such context:

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

ChildComponent is a ponent that includes other ponents but eventually renders simple HTML's <tr>

inside ponent.tsx, I need to get DOM values (offsetTop and clientHeight) for n-th child.

I've tried many things:

  • ReactDOM.findDOMNode(children[n]) gives me:

argument appears to not be a ReactComponent. Keys: $$typeof, type, key, ref, props, _owner, _store

  • children[n].ref just gives me null
  • cannot add ref to children
  • This sort of works:
children.map((child, index) =>
    index === n ? (
        <div style={{display: contents}} key={index} ref={ref}>
    ) : child
)

gives me warning (but works!):

index.js:2178 Warning: validateDOMNesting(...): cannot appear as a child of . in tr (created by FoldControlContainer) ...

is there a better solution? I've tried to use <>, or other "transparent" to DOM ponents instead of div, but it didn't work.

I have a very annoying issue, and I need help with my ponent. It is used in such context:

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

ChildComponent is a ponent that includes other ponents but eventually renders simple HTML's <tr>

inside ponent.tsx, I need to get DOM values (offsetTop and clientHeight) for n-th child.

I've tried many things:

  • ReactDOM.findDOMNode(children[n]) gives me:

argument appears to not be a ReactComponent. Keys: $$typeof, type, key, ref, props, _owner, _store

  • children[n].ref just gives me null
  • cannot add ref to children
  • This sort of works:
children.map((child, index) =>
    index === n ? (
        <div style={{display: contents}} key={index} ref={ref}>
    ) : child
)

gives me warning (but works!):

index.js:2178 Warning: validateDOMNesting(...): cannot appear as a child of . in tr (created by FoldControlContainer) ...

is there a better solution? I've tried to use <>, or other "transparent" to DOM ponents instead of div, but it didn't work.

Share Improve this question edited Feb 12, 2019 at 13:19 Szamanm asked Feb 12, 2019 at 12:35 SzamanmSzamanm 7837 silver badges10 bronze badges 8
  • What's Tr? Please, provide it. children[n].ref just gives me null - why should ref exist? cannot add ref to children - why? – Estus Flask Commented Feb 12, 2019 at 12:39
  • Ah sorry, forgot about that, but that's a regular tr :). I'll update my code – Szamanm Commented Feb 12, 2019 at 12:39
  • In case it's <tr>, you would be able to get DOM element with a ref. What exactly did you try with refs? – Estus Flask Commented Feb 12, 2019 at 12:41
  • @estus: well, I couldn't just children[n].ref = myRef, maybe there's some function for that but couldn't find it – Szamanm Commented Feb 12, 2019 at 12:42
  • 1 No, there won't be ref if you didn't provided a ref, reactjs/docs/refs-and-the-dom.html . I'll try to provide an answer. In case it's not really <tr>, consider updating the question with your real case because it's different. – Estus Flask Commented Feb 12, 2019 at 12:52
 |  Show 3 more ments

2 Answers 2

Reset to default 4

use React.cloneElement to set the refs for the children: https://reactjs/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>
    );
  }
} 

here is a link to a full working example: https://stackblitz./edit/react-cf33ge Open the console at the bottom right to see the output.

findDOMNode expects an instance of React.Component. Components should be rendered with refs in order to get instances. Since refs aren't used in <ChildComponent>/* ... */</ChildComponent> children, they should be cloned with a ref.

If children are supposed to be class ponent elements and their amount doesn't change during parent ponent lifespan, the case can be simplified to:

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 element is available as ReactDOM.findDOMNode(this.childRefs[n].current) when the ponent is mounted.

发布评论

评论列表(0)

  1. 暂无评论