I am trying to get the height on an element.
I want the parent div to adjust its height to the first paragraph of its children paragraph elements. Then a "Read More"/"Read Less" button expands the parent div to reveal all paragraphs or shrinks to only one paragraph.
I have experimented with useEffect, useLayoutEffect and componentDidMount in a class component and they all seem to need a setTimeout delay for the parent div to attain the perfect height.
Sorry if my code is fuzzy. I am new to React. :)
TIA
import styled from 'styled-components'
import React, { useRef, useLayoutEffect, useState } from 'react'
const CatIntroStyled = styled.div`
width: 1000px;
margin: 0 auto;
button{
display: block;
margin: 0 auto;
background: none;
}
button:focus{
outline: none;
}
`
const IntroText = styled.div`
height: ${({introStyle})=>{
if(introStyle.initIntroHeight === "auto") return "auto"
return introStyle.introExpanded ? introStyle.initIntroHeight+"px": introStyle.initFirstPara+"px";
}};
overflow: hidden;
transition: all 1s;
margin-bottom: 2rem
`
const formatIntro = (text, paraRef)=>{
let formatedText = text.replace(/<[^>]*>?/gm, "").replace(/\n\r/g, "")
let returnText = formatedText.split("\r\n").map((paragraph, key) => {
if(key===0) return <p ref={paraRef} key={key}>{paragraph}</p>;
return <p key={key}>{paragraph}</p>
})
return returnText
}
const CatIntro = ({title, text})=>{
const firstIntroPara = useRef();
const introRef = useRef();
const [intro, setIntro] = useState({
initFirstPara: 0,
initIntroHeight: "auto",
introExpanded: false
})
useLayoutEffect(()=>{
setTimeout(()=>{
setIntro({
...intro,
initIntroHeight: introRef.current.offsetHeight,
initFirstPara: firstIntroPara.current.offsetHeight,
})
}, 1000)
}, [])
return(
<CatIntroStyled>
<h1 className="globalTitleStyle">{title}</h1>
<IntroText ref={introRef} introStyle={intro}>
{formatIntro(text, firstIntroPara)}
</IntroText>
<button onClick={(e)=>{
setIntro({
...intro,
introExpanded: !intro.introExpanded
})
}}>{ intro.introExpanded ? "READ LESS": "READ MORE" }</button>
</CatIntroStyled>
)
}
export default CatIntro
Is there a more robust way of knowing when elements are truly painted on the screen?
TIA