ReactJS get rendered component height

前端 未结 9 1596
夕颜
夕颜 2020-12-29 02:29

I\'m attempting to integrate or create a React version of https://github.com/kumailht/gridforms, to do so I need to normalize the height of the columns inside of the row. Th

相关标签:
9条回答
  • 2020-12-29 03:06

    I'd rather do it in componentDidUpdate, but by making sure a condition is met to prevent an infinite loop:

      componentDidUpdate(prevProps, prevState) {
        const row = document.getElementById('yourId');
        const height = row.clientHeight;
        
        if (this.state.height !== height) {
          this.setState({ height });
        }
      }

    0 讨论(0)
  • 2020-12-29 03:12

    My personal opinion is to try and avoid using static and measured sizes like this if you can avoid it because it can complicate the application unnecessarily. But sometimes you cannot get around it. Your component will need to be mounted before you can get a size from it.

    General approach:

    • Give the element a ref
    • When the element is rendered, grab the ref and call .clientHeight and/or .clientWidth
    • Put the values on the state or pass with props
    • Render the element that needs the size from the state variables

    In your case you want to grab the size of a column you can do something like:

    GridRow = React.createClass({
      render(){
            const children = _.map(this.props.children, child => {
                child.props.height = // somehow get row component height
                return child
            })
    
        return (<div data-row-span={this.props.span} {...this.props}>
          <GridCol onSizeChange={(size) => {
    
             //Set it to state or whatever
             console.log("sizeOfCol", size);
          }} />
        </div>)
      }
    })
    
    GridCol = React.createClass({
    
      componentDidMount(){
    
        //Set stizes to the local state
        this.setState({
           colH: this.col.clientHeight,
           colW: this.col.clientWidth
        }); 
    
        //Use a callback on the props to give parent the data
        this.props.onSizeChange({colH: this.col.clientHeight, colW: this.col.clientWidth})
    
      }
    
      render(){
        //Here you save a ref (col) on the class
        return (<div ref={(col) => {this.col = col}} data-field-span={this.props.span} style={{height:this.props.height}} {...this.props}>
          <.... >
        </div>)
      }
    })
    
    0 讨论(0)
  • 2020-12-29 03:17

    A bit more late, but I have an approach which can be used without using the getElementById method. A class based component could be created and the sample code can be used.

    constructor(props) {
      super(props);
      this.imageRef = React.createRef();
    }
    
    componentDidMount(){
      this.imageRef.current.addEventListener("load", this.setSpans);
    }
    
    setSpans = () => {
      //Here you get your image's height
      console.log(this.imageRef.current.clientHeight);
    };
    
    render() {
      const { description, urls } = this.props.image;
      return (
        <div>
         <img ref={this.imageRef} alt={description} src={urls.regular} />
        </div>
      );
    }
    
    0 讨论(0)
  • 2020-12-29 03:22

    According to current React docs, the preferred use of refs is to pass it a callback rather than a string to be accessed elsewhere in this.refs. So to get the height of a div (within a React.Component class):

    componentDidMount() {
      this.setState({ elementHeight: this.divRef.clientHeight });
    }
    
    render() {
      return <div ref={element => this.divRef = element}></div>
    }
    

    Or it works this way, though I don't know if this is advisable since we set state in the render method.

    getHeight(element) {
      if (element && !this.state.elementHeight) { // need to check that we haven't already set the height or we'll create an infinite render loop
        this.setState({ elementHeight: element.clientHeight });
      }
    }
    
    render() {
      return <div ref={this.getHeight}></div>;
    }
    

    Reference: https://facebook.github.io/react/docs/more-about-refs.html

    0 讨论(0)
  • 2020-12-29 03:26

    Don't know about anyone else but I always have to get it on the next tick to be sure of getting the correct height and width. Feels hacky but guessing it's to do with render cycle but I'll take it for now. onLayout may work better in certain use cases.

    componentDidMount() {
      setTimeout(() => {
        let ref = this.refs.Container
        console.log(ref.clientHeight)
        console.log(ref.clientWidth)
      }, 1)
    }
    
    0 讨论(0)
  • 2020-12-29 03:26

    According this answer sizes of a component can be turned out having zero width or height inside componentDidMount event handler. So I'm seeing some ways to solve it.

    1. Handle the event on top-level React component, and either recalculate the sizes there, or redraw the specific child component.

    2. Set the load event handler on the componentDidMount to handle loading the cells into the react component to recalculate the proper sizes:

      componentDidMount = () => {
         this.$carousel = $(this.carousel)
         window.addEventListener('load', this.componentLoaded)
      }
      

      Then in the componentLoaded method just do what you need to do.

    0 讨论(0)
提交回复
热议问题