どちらもエフェクトを実行しますが、ブラウザのペイントに対するタイミングが異なり、そのタイミングの差こそが要点です。
useEffectはブラウザがペイントした後に実行されます。非同期かつ非ブロッキングです。ほぼすべての用途(データ、サブスクリプション、ロギング)に使います。useLayoutEffectは DOM が変更された後、ブラウザがペイントする前に同期的に実行されます。レイアウトを読み取り、同じフレーム内で DOM を変更して、目に見えるちらつきを避けたい場合に使います。
text
render → DOM updated → [useLayoutEffect runs] → browser paints → [useEffect runs]
