useLayoutEffectによるDOM要素の測定
レイアウト後かつ描画前に要素の寸法、位置、スクロールオフセットを読み取り、ちらつきを防ぎます
「useLayoutEffectによるDOM要素の測定」はCoddyKit上の無料React Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはReact Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 React Academyコースには全4レッスンが含まれています。
getBoundingClientRectの概要
element.getBoundingClientRect()は、ビューポートを基準とした要素のサイズと位置を含むDOMRectオブジェクトを返します。含まれる値はtop、right、bottom、left、width、heightです。正確な値を返すためにブラウザにレイアウト計算を実行させるため、呼び出しは必要最小限にしてください。
useEffect内で読み取る問題点
useEffect内でgetBoundingClientRect()を読み取ると、その時点ですでにブラウザのペイントが完了しています。その後、測定結果に基づいてstateを設定すると、Reactが再レンダーし、ブラウザがもう一度ペイントします。2回目のペイントで修正されるまで、要素が一時的に誤った位置やサイズで表示される可能性があります。
useLayoutEffectで解決できる理由
useLayoutEffectで測定値を読み取る処理は、DOMの変更後かつペイント前に行われます。測定によってstateが更新されると、Reactは同期的に再レンダーして修正済みのDOMをコミットします。これらはすべてブラウザが何もペイントする前に行われるため、ユーザーには1回のペイントサイクルで最終的な正しい結果だけが表示されます。
ツールチップの配置
ツールチップはトリガーとなる要素の近くに表示する必要があります。useLayoutEffect内でgetBoundingClientRect()を使ってトリガー要素の位置を測定し、ツールチップの絶対位置を計算して、その位置をstateに設定してください。最初のペイントからツールチップが正しい位置に表示されるため、誤った初期位置から目に見えて移動することがありません。
要素のアニメーション:初期サイズの読み取り
要素を本来の(制約のない)サイズから固定サイズへアニメーションさせるには、制約を適用する前に本来のサイズを知る必要があります。useLayoutEffectでアニメーション用のスタイルを適用する前に要素の高さを読み取り、stateに保存してから、CSSトランジションの開始キーフレームの値として使用してください。
固定ヘッダーの高さ
ページに固定ヘッダーがある場合、本文コンテンツがヘッダーの背後に隠れないよう、ヘッダーの高さと同じ上部パディングが必要です。refを使い、useLayoutEffect内でheaderRef.current.getBoundingClientRect().heightによってヘッダーの高さを測定します。これをコンテンツコンテナのpaddingTopに設定してください。最初のレンダーからレイアウトが正しくなります。
state更新による同期的な再レンダー
useLayoutEffect内でsetStateを呼び出すと、Reactは同じ同期処理ブロック内で、もう一度レンダーとコミットのサイクルを直ちに実行します。この再レンダーではuseLayoutEffectも再度実行されます。無限ループを作らないよう注意してください。新しい測定値が現在のstateの値と異なる場合にだけ、stateを更新します。
SSR:測定結果が0になる理由
サーバー上にはDOM要素が存在しないため、getBoundingClientRect()は例外を投げるか、0を返します。useLayoutEffectを次のチェックでガードしてください。if (typeof window === 'undefined') return;SSRアプリでは、プレースホルダーのサイズでハイドレーションし、クライアント側でハイドレーション後に測定する必要がある場合があります。
継続的な追跡のためのResizeObserver
useLayoutEffectによる1回限りの測定では、マウント時のサイズしか取得できません。ウィンドウのリサイズ、動的なコンテンツ、CSSの変更などによる要素のサイズ変化を追跡するには、代わりにResizeObserverを使用してください。要素のサイズが変化するたびにコールバックを実行するため、レスポンシブなコンポーネントに適しています。
不要な測定を避ける
複数のエフェクトで同じ測定値が必要な場合は、1回だけ計算し、コンテキストで共有するかpropsとして渡してください。複数のuseLayoutEffect呼び出しで同じgetBoundingClientRect()の値を計算すると、同期的なレイアウト読み取りが複数回発生し、それぞれに比較的大きなコストがかかります。可能な場合は測定をまとめてください。
useLayoutEffectでのrefのタイミング
refはエフェクトが実行される前に設定されます。useLayoutEffectが実行される時点では、ref.currentがDOM要素を指していることが保証されています。そのため、次のパターンが機能します。useLayoutEffect(() => { const rect = ref.current.getBoundingClientRect(); ... }, [])マウント済みのコンポーネントでは、レイアウトエフェクト内でrefがnullになることはありません。
getBoundingClientRectのタイミング
getBoundingClientRect()をuseEffect内よりもuseLayoutEffect内で呼び出すほうがよいのはなぜですか?
レッスンのまとめ:DOM要素の測定
getBoundingClientRect()はuseLayoutEffect内で使用し、DOMの変更後かつペイント前にDOMの測定値を読み取ります。これらの測定結果によるstate更新は、同じペイントに含まれる同期的な再レンダーを引き起こすため、ちらつきを防げます。typeof windowのチェックでSSRに対応してください。継続的にサイズを追跡する場合は、ResizeObserverを優先してください。
AI チューターと学ぶ React — 無料
ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。
- コース
- 88
- レッスン
- 324
よくある質問
「useLayoutEffectによるDOM要素の測定」レッスンは無料ですか?
はい。「useLayoutEffectによるDOM要素の測定」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、React Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 React Academyコースには全4レッスンが含まれています。
「useLayoutEffectによるDOM要素の測定」で何を学びますか?
レイアウト後かつ描画前に要素の寸法、位置、スクロールオフセットを読み取り、ちらつきを防ぎます ブラウザで直接実行するハンズオンコードでReact Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
React Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのReact Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「useLayoutEffectによるDOM要素の測定」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このReact Academyレッスンでコードを書いて実行できますか?
はい。すべてのReact Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- レンダリングフェーズとDOMコミット
- useLayoutEffectとuseEffectの実行タイミング
- useLayoutEffectによるDOM要素の測定
- レイアウトスラッシングと視覚的なちらつきの回避