admin管理员组

文章数量:1305656

I need to access the heights of child ponents 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 Blocks 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 Blocks 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 ponents 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 Blocks 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 ponent 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 ponent otherwise I'm going to have some of it's logic in an unrelated ponent 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.

I need to access the heights of child ponents 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 Blocks 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 Blocks 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 ponents 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 Blocks 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 ponent 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 ponent otherwise I'm going to have some of it's logic in an unrelated ponent 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.

Share Improve this question edited Apr 20, 2017 at 10:30 ollie asked Apr 20, 2017 at 10:04 ollieollie 8232 gold badges12 silver badges24 bronze badges 3
  • What if each generic block will be responsible for its own size calculations, sending the results back into parent via given endpoint? – raina77ow Commented Apr 20, 2017 at 10:46
  • eles.map(e => <Block ref={ref => this.blocks[e] = this.blocks[e] || ref} key={e}>{e}</Block>) and you will have all required refs in ponentDidMount() – elmeister Commented Apr 20, 2017 at 10:50
  • I didn't think of creating the refs in the Blocks ponent, that's much simpler than anything I was trying to do. Am I right in thinking there's no way to do this without refs? I know we've had trouble with testing before (and everything I read seems to try and dissuade me from using them). Submit this as an answer and I'll accept - cheers @elmeister – ollie Commented Apr 20, 2017 at 11:07
Add a ment  | 

1 Answer 1

Reset to default 8

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 {
  ponentDidMount() {
    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 ponentDidMount method, you can get the Block ponent height or other property. index.js

const eles = [0, 1, 2, 3, 4];

class App extends Component {
  constructor() {
    super();
    this.blocks = [];
  }


  ponentDidMount() {
    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'));

the result in console

本文标签: javascriptGet heights of child components in ReactStack Overflow