UseLayoutEffect inconsistent behavior
See original GitHub issueAssuming the useLayoutEffect
should fire after DOM is painted, there’s a bug where the elements are not yet flushed to DOM for the initial invocation of useLayoutEffect
when it’s used in a component that’s rendered as a nested child:
Case 1:
return <CompoUsingLayoutEffect/>
Case 2:
return <div>
<CompoUsingLayoutEffect/>
</div>
In case 2, the useLayoutEffect
is initially fired before the DOM is painted. While in case 1, it works as expected.
Consecutive executions of useLayoutEffect
are called after the DOM is painted.
Best if you check the repro yourself:
Preact: https://codesandbox.io/s/agitated-morse-b6zrp?expanddevtools=1 React: https://codesandbox.io/s/hardcore-hertz-p5up6?expanddevtools=1
In the repros above, all textareas should be initially resized to fit the content, but in Preact the first textarea is initially set to height: 0
because the scrollHeight
is read before the textarea
is in the DOM (check the console for 0 false
which indicates the element isn’t in the document
).
Preact 10.0.0-rc.1
Issue Analytics
- State:
- Created 4 years ago
- Reactions:4
- Comments:7 (5 by maintainers)
FYI, I think #2012 fixes this issue. I tried your text area demo with it and I think it resolved it
Yes, good point about
useEffect
.My misconceptions around these things mainly arise from the fact (as I’ve edited the comment above just when you posted your reply) that I don’t know how event loop frames relate to animation frames (
setTimeout
vsrequestAnimationFrame
), and what React actually uses to scheduleuseEffect
(I tried looking into React source, but there’s an insane amount of abstractions, coupled with Flow, and it’s unreadable to me).