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.
-
What's
Tr
? Please, provide it. children[n].ref just gives me null - why shouldref
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
2 Answers
Reset to default 4use 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.