アニメーション前の測定に useLayoutEffect を使う
アニメーション開始前に useLayoutEffect で要素の寸法を測定し、レイアウトのずれを防ぎます。
「アニメーション前の測定に useLayoutEffect を使う」はCoddyKit上の無料React Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはReact Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 React Academyコースには全4レッスンが含まれています。
フラッシュ問題
要素が初回レンダリング時に目に見えて跳ねたり、ちらついたりしてから所定の位置に収まることがあります。これは通常、ブラウザーがすでに要素を描画した後で、そのサイズを測定したり位置を変更したりする場合に発生します。
ユーザーには 1 フレームの間だけ誤った位置が見え、その後突然修正されるため、壊れているように見えます。
useEffect がちらつきを引き起こす理由
useEffect はブラウザーが描画した後に実行されます。そのため、useEffect 内でサイズを読み取って DOM を更新すると、変更が適用される前に、ユーザーはすでに修正前のフレームを見てしまいます。
ユーザーに見えない状態で行う必要がある視覚的な位置調整では、描画後のタイミングでは遅すぎます。
useLayoutEffect は描画前に実行される
useLayoutEffect は、React が DOM を変更した直後で、ブラウザーが描画する前に同期的に実行されます。ここで行った DOM の読み取りや書き込みは、ユーザーに 1 フレームも見られることなく反映されます。
そのため、最初から正しい状態で表示する必要があるサイズ測定や位置調整に適しています。
初期位置を測定する
useLayoutEffect 内では、ref.current.getBoundingClientRect() を使って要素のレイアウトを読み取り、アニメーションを開始する前の位置とサイズを取得できます。
描画前に実行されるため、目に見えるちらつきを発生させずに、測定と開始時の transform の適用を行えます。
FLIP テクニック
FLIP は First、Last、Invert、Play の略です。要素の First の位置を記録し、Last の位置へ移動させた後、視覚的に First へ戻す transform を適用して Invert し、最後にその transform を取り除いて Last へアニメーションさせるのが Play です。
実際のレイアウトが瞬時に変化しても、低コストな transform だけを使ってレイアウトの変更をアニメーションさせられます。
useLayoutEffect で getBoundingClientRect を使う
重要な読み取り処理は useLayoutEffect 内で行います。変更前に First の rect を取得し、変更後に Last の rect を取得してから、差分を計算します。描画前に処理するため、何も表示される前に反転用の transform が確実に設定されます。
2 つの rect の差から、反転に必要な正確な translate と scale を求められます。
同期的に Transform を適用する
useLayoutEffect 内で反転用の transform を同期的に設定し、次のフレームでそれを取り除いて、要素を本来の位置へアニメーションさせます。多くの場合、requestAnimationFrame で再生の段階を開始します。
描画前に反転処理が適用されるため、ユーザーが要素を Last の位置にそのまま見ることはありません。
SSR に関する警告
サーバーには DOM が存在しないため、React はサーバーレンダリング中に useLayoutEffect が何もしないという警告を出力します。レイアウトエフェクトはブラウザーでのみ意味を持ちます。
この警告は、測定対象が存在しない環境ではエフェクトを実行できないことを示しています。
SSR に安全な代替方法
コンポーネントをサーバーで実行する必要がある場合は、useEffect と requestAnimationFrame を組み合わせて次の描画前に測定するか、ブラウザーでのみ条件付きで useLayoutEffect を使用します。
これにより警告を避けながら、重要度の低いアニメーションでも描画直前に近いタイミングを実現できます。
アコーディオンを展開する例
高さのアニメーションは典型的な例です。useLayoutEffect で折りたたみ時と展開時の高さを測定し、明示的なピクセル値の間でアニメーションさせると、トランジションが滑らかになります。
auto の高さはアニメーションできないため、先に実際の高さを測定することで、具体的な数値へのトランジションが可能になります。
useLayoutEffect を使うタイミング
ほとんどの処理では、まず useEffect を使用してください。レイアウトを読み取り、目に見えるちらつきを避けるために描画前に DOM を変更する必要がある場合に限り、useLayoutEffect を使用します。
使いすぎると、処理が完了するまで描画をブロックするため、パフォーマンスが低下することがあります。
理解度チェック
エフェクトの実行タイミングについての理解度を確認しましょう。
まとめ
フラッシュ問題は描画後に測定することで発生すること、useLayoutEffect は描画前に実行されること、そして FLIP テクニックによって低コストな transform でレイアウトの変更をアニメーションさせる方法を学びました。
また、SSR に関する警告と、useEffect と requestAnimationFrame を組み合わせた代替方法も確認しました。
よくある質問
「アニメーション前の測定に useLayoutEffect を使う」レッスンは無料ですか?
はい。「アニメーション前の測定に useLayoutEffect を使う」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、React Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 React Academyコースには全4レッスンが含まれています。
「アニメーション前の測定に useLayoutEffect を使う」で何を学びますか?
アニメーション開始前に useLayoutEffect で要素の寸法を測定し、レイアウトのずれを防ぎます。 ブラウザで直接実行するハンズオンコードでReact Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
React Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのReact Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「アニメーション前の測定に useLayoutEffect を使う」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このReact Academyレッスンでコードを書いて実行できますか?
はい。すべてのReact Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- Reactの状態変更によるCSSトランジション
- ReactでのCSSキーフレームアニメーション
- アニメーション前の測定に useLayoutEffect を使う
- ライブラリを使わない入退場アニメーション