I'm calling a useCallback from a useEffect that will make the component's height change. Then, to end the effect, I'd like to scroll the component to a specific point. The issue is that the scroll operation does not work because it fires to soon : the DOM did not update yet.
If I wrap it in a setTimeout it does work (because it fires once the DOM updated), but it's kind of hacky.
Is there a clean way to wait for the DOM to render before pursuing the effect?
Does not work:
const viewportElement = useRef()
cont [innerHeight, setInnerHeight] = useState(0)
refreshDOM = useCallback(() => {
setInnerHeight(500) // Will cause the DOM to refresh and the inner div to grow in height.
}, [setInnerHeight])
useLayoutEffect(() => {
refreshDOM() // DOM updates
viewportElement.current.scroll(0, 200) // Fires to soon: innerDiv is still too small
}, [refreshDOM, someOtherStuffTriggeringTheEffect])
return (
<div ref={viewportElement} style={{height: 100}}>
<div style={{height: innerHeight}}></div>
</div>
)
Works:
// ...
useLayoutEffect(() => {
refreshDOM() // DOM updates
setTimeout(
() => viewportElement.current && viewportElement.current.scroll(0, 200),
0,
) // DOM was refreshed, scroll operation works
}, [refreshDOM, someOtherStuffTriggeringTheEffect])
// ...