I'm trying to understand which lifecycle point CSS styles are starting to apply to DOM element(s).
Run onto a problem where I need to get the element's clientWidth
after all styles are applied. My tests shows that I can not rely on useEffect
hook, because I get inconsistent result.
I test it with a simple <did/>
element, which is should take full parent width (grid container).
const divRef = useRef()
useEffect(() => {
console.log(divRef.current.clientWidth)
})
<div class="parent">
<div ref={divRef} class="child" />
</div>
I expect the width === 280px, but get (lets say) 980px most of the time. If I put console.log
inside a timeout
everything starts to work as expected. Clearly useEffect
runs before styles are applied.
Can someone clarify for me how I can get reliable result?
You can use the second argument of useEffect to keep track of the value of a variable.
const divRef = useRef()
const [divWidth, setDivWidth] = React.useState('');
useEffect(() => {
setDivWidth(divRef.current.clientWidth)
}, [divWidth]) // Only re-run the effect if divWidth changes
I've also found another StackOverflow question that might help you:
React doesn't really get any more involved with CSS than emitting class
and style
attributes to DOM attributes. It never "applies" CSS, and really what you probably mean could be a conglomeration of a bunch of things that could be happening in the DOM:
See What forces layout/reflow to get an idea of the scope of this.
Sadly, HTML doesn't have a DOM event for when an element's layout changes or when reflows occur, so if you need to get element dimensions, you have to hack it. One unsophisticated technique is a polling loop that periodically checks the dimensions of the DOM element. If you don't want to continuously poll, you could maybe cut off the poller after some time and add a window resize event listener to adjust the dimensions
function YourComponent() {
const [width, setWidth] = useState(0);
const divRef = useRef(null);
function checkWidth() {
if (divRef.current && divRef.current.clientWidth !== width) {
setWidth(divRef.current.clientWidth);
}
}
useEffect(() => {
const interval = setInterval(checkWidth, 1000);
return () => clearInterval(interval);
}, []);
useEffect(() => {
window.addEventListener('resize', checkWidth);
return () => window.removeEventListener('resize', checkWidth);
}, []);
return (
<div ref={divRef}>
...
</div>
);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.