2

I'm dynamically rendering a list of Symbol(react.element) by mapping into an array and placing each of its elements HTML tags. My question is therefore: how can I get the height of each of the rendered Symbol(react.element)? This seems not to be in the Symbol(react.element)'s object.

Thanks in advance for your help

cyruslk
  • 839
  • 3
  • 13
  • 25
  • 1
    Take a look at https://stackoverflow.com/questions/43817118/how-to-get-the-width-of-a-react-element – Bruno Mazzardo Jun 07 '18 at 18:32
  • Have you tried getting `.offsetHeight` of the element? Here is [how to access element in modern react](https://stackoverflow.com/a/38093981/8122487). Also, what do you make symbols of your elements for? – RaphaMex Jun 07 '18 at 19:36

4 Answers4

9

Actually, if you are using Functional Components, would be better to isolate this resize logic in a custom hook instead of leave it inside the component. You can create a custom hook like this:

const useResize = (myRef) => {
  const [width, setWidth] = useState(0)
  const [height, setHeight] = useState(0)

  const handleResize = () => {
    setWidth(myRef.current.offsetWidth)
    setHeight(myRef.current.offsetHeight)
  }

  useEffect(() => {
    myRef.current && myRef.current.addEventListener('resize', handleResize)

    return () => {
      myRef.current.removeEventListener('resize', handleResize)
    }
  }, [myRef])

  return { width, height }
}

and then you can use it like:

const MyComponent = () => {
  const componentRef = useRef()
  const { width, height } = useResize(componentRef)

  return (
    <div ref={componentRef}>
      <p>width: {width}px</p>
      <p>height: {height}px</p>
    <div/>
  )
}
Samshel
  • 928
  • 8
  • 12
Marco Antônio
  • 880
  • 8
  • 15
5
 class MyComponent extends Component {
      constructor(props){
        super(props)
        this.myDiv = React.createRef()
      }

      componentDidMount () {
        console.log(this.myDiv.current.offsetHeight)
      }

      render () {
        return (
          <div ref={this.myDiv}>element</div>
        )
      }
    }
Philippe
  • 960
  • 2
  • 12
  • 29
2

A modified version of Marcos answer.

I've placed a rendering bool to make sure all data is rendered before placing the height and width. This is to be sure that the height is calculated with all required elements in place instead of risking receiving an incorrect height and width.

useResize hook placed in a separate folder:

import { useState, useEffect, useCallback } from 'react';

export const useResize = (myRef: React.MutableRefObject<any>, rendering: boolean) => {
    const [width, setWidth] = useState(0);
    const [height, setHeight] = useState(0);

    const handleResize = useCallback(() => {
        setWidth(myRef.current.offsetWidth);
        setHeight(myRef.current.offsetHeight);
    }, [myRef]);

    useEffect(() => {
        if (!rendering) {
            myRef.current && myRef.current.addEventListener('resize', 
            handleResize(), { once: true });
        }
    }, [myRef, handleResize, rendering]);

    return { width, height };

Example of usage:

const MyComponent = ({ A, B }) => {

  // A and B is data that is required in component

  const componentRef = useRef()
  const { width, height } = useResize(componentRef, !A || !B)

  if (!A || !B) return;

  return (
    <div ref={componentRef}>
      <p>{A} {width}px</p>
      <p>{B} {height}px</p>
    <div/>
  )
}
Westman
  • 202
  • 2
  • 4
1

const componentRef = useRef(null) and div ref={componentRef}