An effect with an empty dependency array runs once after the first render, which resembles a mount hook and differs in when it fires and what it can see.
useEffect(() => {
// runs AFTER paint. componentDidMount ran before it.
}, [])
useLayoutEffect(() => {
// runs before paint — this is the closer analogue,
// and it blocks the browser, so use it only for
// measurements that would otherwise flash.
}, [])
// and the empty array is a claim: this effect reads
// nothing from props or state. the linter checks it.
The difference matters for anything measuring the DOM: an effect that reads a height and sets state causes a visible flicker, because the browser painted the first value. The empty array is also a lie in most of the code that has one — it usually reads a prop, and the exhaustive-deps rule flags it, and the flag is disabled with a comment. Reading the comment is nearly always instructive.