I am attempting to code a <List>
component that is able to print the (x, y) coordinates of each <Row>
entry that is added. The problem is that there is an intermediate <RowGroup>
component that holds <Row>
entries, where I plan on having the <RowGroup>
be an abstract type.
I followed this answer regarding innerRef and this answer regarding pushing refs from children components, and I wrote the below code that seems to work.
But it feels kind of hack-ish. Apparently, you must use forwardRef to forward refs, and in this case I am using an innerRef prop and it works? Is it legal to push refs from the child component, into the parent's parent's ref list? I know you aren't supposed to do stuff like having an array of refs, and this feels like a different way to bypass that.
Is there a different way I should structure this code to be more valid? Are there any cases where this code wouldn't work?
import {useRef, useEffect, forwardRef, useImperativeHandle} from 'react';
function App() {
const rowGroups = [
{rows: [{text: "A"}, {text: "B"}, {text: "C"}]},
{rows: [{text: "D"}, {text: "E"}]}
]
return <List rowGroups={rowGroups}></List> // List should be: A B C {spacing} D E
}
const List = ({rowGroups}) => {
let rowRefs = useRef([]);
function handleClick() {
for (let i = 0; i < rowRefs.current.length; i++) {
const rect = rowRefs.current[i].getBoundingClientRect();
console.log(rect.left, rect.top); // print coordinates of each row.
}
}
return (
<div>
<div>
{rowGroups.map((rowGroup, _) => (
<RowGroup key={_} rowGroup={rowGroup} innerRef={rowRefs}/>
))}
</div>
<button onClick={() => handleClick()}></button>
</div>
);
}
const RowGroup = ({rowGroup, innerRef}) => {
return (
<div style={{padding: 50}}>
{rowGroup.rows.map((row, _) => (
<Row key={_} row={row} innerRef={innerRef}/>
))}
</div>
);
};
const Row = ({row, innerRef}) => {
return (
<div ref={(ref) => {innerRef.current.push(ref)}} style={{height: 50, width: 200}}>
{row.text}
</div>
);
}
export default App;
Thanks.