Reputation: 823
I need to access the heights of child components in React but can't find any clear guidance on how best to do it. My Component looks like this:
/* index.js */
import Blocks from './Blocks'
ReactDOM.render(<Blocks />, document.body)
/* Blocks.jsx */
import Block from './Block'
class Blocks extends Component {
render () {
const eles = [0, 1, 2, 3, 4]
return (
<div>
{eles.map(e => <Block key={e}>{e}</Block>)}
</div>
)
}
}
I want to know the size and position of each of those Block
s as I want to position them myself later.
As far as I can see, this approach doesn't allow me to use this.props.children
to access the elements which is annoying as rendering the blocks in this way is much better for me (there's going to be logic around which type of Block
to render later). To get around this I've tried moving the rendering of the Block
s into the index file like this:
/* index.js */
import Blocks from './Blocks'
import Block from './Block'
const eles = [0, 1, 2, 3, 4]
ReactDOM.render(
<Blocks>
{eles.map(e => <Block key={e}>{e}</Block>)}
</Blocks>
)
/* Blocks.jsx */
class Blocks extends Component {
render () {
return (
<div>
{this.props.children}
</div>
)
}
}
What this allows me to do is use refs
inside the individual Block
components to return the result of their getBoundingClientRect
function which I should be able to access through the parent but I'm now reading that using refs
is discouraged and not how React is supposed to be used.
I need to be able to pin certain Block
s to the top of the screen as they are scrolled past and can't think of any other way of doing it than knowing their sizes and positions in a parent component and using that to manage them. Is there any way of doing this? Ideally I would like to move that loop back inside of the Blocks
component otherwise I'm going to have some of it's logic in an unrelated component which doesn't seem right.
I've also looked into using react-sticky
but as the app I'm building is already inside a fixed position element (which is unavoidable) I don't think it'll help me.
Upvotes: 1
Views: 8993
Reputation: 156
try to use callback function in Block Component to send the ref to the Parent Component
Block.js
import React, { Component } from 'react';
class Block extends Component {
componentDidMount() {
this.props.getRef(this.block, this.props.i);
}
render() {
return (
<div ref={n => this.block = n}>
<p>{this.props.children}</p>
</div>
);
}
}
export default Block;
save the refs into variable or state in index.js
,
and then in componentDidMount
method, you can get the Block component height or other property.
index.js
const eles = [0, 1, 2, 3, 4];
class App extends Component {
constructor() {
super();
this.blocks = [];
}
componentDidMount() {
console.log(this.blocks);
this.blocks.forEach((block, i) => {
console.log(i, block.getBoundingClientRect().height)
})
}
getRef = (ref, i) => {
this.blocks[i] = ref;
};
render() {
return (
<div>
{eles.map((e, i) => (
<Block key={e} i={i} getRef={this.getRef}>{e}</Block>
))}
</div>
);
}
}
render(<App />, document.getElementById('root'));
Upvotes: 8