「データ取得は useEffect でやるもの」…本当にそうか?
フロントエンド開発の世界では、「これが王道だ」と信じられているベストプラクティスがいくつもある。
その中でも特に根強いのが、この思い込みだ。
「API からデータを取得するときは useEffect を使う」
確かに、useEffect を使えばコンポーネントのマウント時に API を叩いてデータを取得することができる。
これが「React でデータを取得する最も一般的な方法」だと言っていい。
だが、本当にそれが最適解なのか?
いや、そんなことはない。
Next.js を使うなら、useEffect でデータを取得するのはむしろ「悪手」になり得る。
ここでは、その理由と、より適した代替手段について考えてみよう。
⸻
1. useEffect によるデータ取得の問題点
典型的な useEffect を使ったデータ取得コードを見てみよう。
"use client";
import { useEffect, useState } from "react";
export default function Page() {
const [data, setData] = useState(null);
useEffect(() => {
fetch("/api/data")
.then((res) => res.json())
.then((data) => setData(data));
}, []);
if (!data) return <p>Loading...</p>;
return <div>{data.message}</div>;
}
一見、問題ないように見える。
コンポーネントがマウントされたときに fetch を実行し、データが取得できたら setData で state を更新する。
よくある「React らしいコード」だ。
だが、ここに 3つの問題 がある。
問題①: クライアント側でしか動かない
このコードは useEffect の特性上、クライアントサイドでしか実行されない。
つまり、サーバーサイドレンダリング (SSR) ではデータがない状態でまず HTML を返し、その後クライアント側でデータを取得する。
結果として、ページ表示の速度が落ちる。
ページが表示されるまでの流れ
1. サーバーは空の HTML を返す → 画面には "Loading..." のみが表示される
2. クライアントが fetch で API を叩く → ここで初めてデータを取りに行く
3. データを受け取って state を更新 → ようやくデータが画面に表示される
これでは、ユーザーが待たされる時間が長くなる。
⸻
問題②: 「ちらつき (Flash of Empty Content)」が発生する
ページを開いたとき、一瞬 "Loading..." が表示され、その後データが表示される。
この 「一瞬何もない状態」 がユーザーの体験を悪化させる。
特に、テキストならまだしも、画像やレイアウトが変わる UI では、この「ちらつき」が不快に感じられることが多い。
⸻
問題③: クライアントの負荷が増える
useEffect を使うということは、データ取得の処理を クライアント側に押し付ける ということだ。
本来、これはサーバーで処理したほうが速いし、負荷も分散できる。
たとえば、Next.js の server components を使えば、データを 最初から HTML に埋め込んで返す ことができる。
そうすれば、クライアントが余計なリクエストをする必要もなく、初回レンダリングからデータがある状態になる。
⸻
2. useEffect を使わない Next.js のデータ取得方法
では、どうすればいいのか?
答えは「サーバーでデータを取得してしまうこと」 だ。
Next.js では、fetch をサーバーコンポーネント内で実行できる。
これを活用すれば、クライアントがデータを取りに行く前に、すでにサーバーがデータを埋め込んで返す ことができる。
改善版: サーバーコンポーネントでデータを取得
// app/page.tsx
(App Router)
export default async function Page() {
const res = await fetch("https://jsonplaceholder.typicode.com/posts/1");
const data = await res.json();
return <div>{data.title}</div>;
}
この方法なら、次のようなメリットがある。
• ページが表示された瞬間にデータがある
• クライアント側で fetch する必要がない
• SSR (サーバーサイドレンダリング) が効くので SEO も強い
特に、SEO を重視するサイトでは 「ページ表示の瞬間にデータがある」 ことが重要だ。
Google の検索エンジンは 「最初の HTML にデータが含まれているかどうか」 を評価基準にしているからだ。
⸻
3. それでも useEffect を使うべきケース
では、useEffect は完全に不要なのか? いや、そんなことはない。
クライアントサイドでの動的データ取得が必要な場合には、useEffect を使うのが正解だ。
useEffect を使うべき場面
• ユーザーの操作に応じてデータを取得する
• 例: 検索ボタンを押したとき
• リアルタイム更新が必要なデータ
• 例: WebSocket を使ったチャット
• クライアント固有のデータ (ローカルストレージ, クッキー)
• 例: ユーザーの設定情報の取得
これらのケースでは、useEffect の使用は適切だ。
だが、「ページロード時にデータを取得するだけ」なら、useEffect ではなく サーバーコンポーネント を使うべきだ。
⸻
結論
「データ取得は useEffect でやるもの」
—いや、そんなことはない。
Next.js を使うなら、サーバーコンポーネントや fetch を活用して、最初からデータを埋め込んで返す のがベストだ。
むやみに useEffect を使うと、ページの表示速度が遅くなり、UX も悪化する。
これからの Next.js でのデータ取得の鉄則
ページロード時のデータ取得 → サーバーでやる
ユーザー操作に応じたデータ取得 → クライアントでやる
「useEffect を使うのが当たり前」と思っているなら、一度立ち止まって考えてみてほしい。
それは本当に最適解なのか? いや、もっといい方法があるのではないか?