reactjsnext.jsreact-hooksuse-ref

Get the height of an element and show/hide More... button depending on the element's height


I'm new to React and NextJs. I want to get the height of an element and depending on its height, to show or not to show the More... button.

What I've tried is this:

import {useRef, useState} from "react";

const MyText = (props) => {
  const [myState, setMyState] = useState(null)
  const setContent = (e) => {
    setMyState(e)
  }

  const myRef = useRef(null)
  const needsMoreButton = () => {
    console.log(myRef) // It's null
    console.log(myState) // It's null too!
  }


  return (
    <div>
      <p ref={myRef} onLoad={setContent} className="max-h-20 overflow-hidden">If it has multiple lines of text, to show "More..." and if it has only one line of text, not to show "More..."</p>
      {
        needsMoreButton() && <button>More...</button>
      }
    </div>
  )
}

export default MyText

So it seems the onLoad is not triggered and myRef is not filled with the p tag.


Solution

  • The onLoad event is not supported by the p element, so it won't work as you expect. Instead, you can use the useEffect hook to calculate the height of the element after it has been rendered.

    import {useRef, useState, useEffect} from "react";
    
    const MyText = (props) => {
     const [needsMoreButton, setNeedsMoreButton] = useState(false)
     const myRef = useRef(null)
    
    useEffect(() => {
     const height = myRef.current.clientHeight
     setNeedsMoreButton(height > 20) // or any other threshold you choose
    },   [])
    
    return (
      <div>
        <p ref={myRef} className="max-h-20 overflow-hidden">If it has multiple 
      lines of text, to show "More..." and if it has only one line of text, not 
      to show "More..."</p>
       {
         needsMoreButton && <button>More...</button>
       }
      </div>
       )
     }
    
    export default MyText