Closed13

useLayoutEffectのdocsを読む

hajimismhajimism

Reference

useLayoutEffect(setup, dependencies?) 

'a version of useEffect that ...' ということでuseEffectでありますけれども、

The code inside useLayoutEffect and all state updates scheduled from it block the browser from repainting the screen. When used excessively, this makes your app slow. When possible, prefer useEffect.

という一点には注意する。なるほど、たしかにユーザーに画面を早く届けるためには、とりま画面更新→Effectの計算となるわけだが、画面更新される前に計算しておきたいものはuseLayoutEffectを使う必要があって、計算量次第ではユーザー体験下げるから気をつけてねってことね。

hajimismhajimism

Usage

Tooltipの表示位置を計算する例が載っている。

計算手順Deepl訳

  1. ツールチップは、初期のtooltipHeight = 0でレンダリングされます(そのため、ツールチップの位置がおかしくなる可能性があります)。
  2. ReactはこれをDOMに配置し、useLayoutEffectのコードを実行します。
  3. useLayoutEffectは、ツールチップコンテンツの高さを測定し、即座に再レンダリングをトリガーします。
  4. ツールチップは、実際のtooltipHeightで再レンダリングされます(ツールチップが正しく配置されるように)。
  5. ReactはDOM内のそれを更新し、ブラウザは最終的にツールチップを表示します。
hajimismhajimism

まあTooltipは最初隠れているから、それならpaintingをブロックしない方がいいのかもしれない

hajimismhajimism

Troubleshooting

Layoutの計算はもちろんユーザークライアント側でしか計算できないので、サーバーでもレンダリング時にはできず、しばしばHydration errorが起こる。

いくつかの対策がある。

hajimismhajimism

Replace useLayoutEffect with useEffect. This tells React that it’s okay to display the initial render result without blocking the paint (because the original HTML will become visible before your Effect runs).

RadixはSSR対応としてuseEffctを選んでいたのかもしれない?

hajimismhajimism

Alternatively, mark your component as client-only. This tells React to replace its content up to the closest <Suspense> boundary with a loading fallback (for example, a spinner or a glimmer) during server rendering.

client-onlyにするとSSR時にはSuspendするようになってるのふつうに知らんかった

hajimismhajimism

Alternatively, you can render a component with useLayoutEffect only after hydration.

isMountedみたいなStateを持つ対策方法

hajimismhajimism

If you synchronize your component with an external data store and rely on useLayoutEffect for different reasons than measuring layout, consider useSyncExternalStore instead which supports server rendering.

useSyncExternalStoreはsupports server rendering.らしい。正味使い方知らない。Effectシリーズとして次はこれを読みに行きたい。

このスクラップは2023/07/07にクローズされました