最後の章です。いまデータはsrc/data/birds.jsに直接書いてあります。これを外のファイルに出して、読みこむ形に変えます。
見た目は何も変わりません。変わるのは「データがどこから来るか」です。
なぜ外に出すのか
data/birds.jsはアプリのコードの一部なので、中身を書きかえるたびにビルドし直しになります。実務では、データはたいてい外にあります。
- サーバーのAPIから受け取る
- CMS(WordPressのREST APIなど)から受け取る
- JSONファイルとして置いておく
このコースではJSONファイルでやります。外部のサービスに頼らないので、手元で確実に動きます。
public/に置いたファイルはそのまま公開される
Viteのプロジェクトでは、public/フォルダの中身は加工されずにそのままの名前で配信されます。
shima-zukan/
├── public/
│ └── birds.json ← /birds.jsonでアクセスできる
└── src/src/に置いたファイルはビルドで名前が変わりますが、public/は変わりません。外から取りにいくファイルはこちらに置きます。
useEffectの形
読みこみはuseEffectの中で行います。
import { useEffect, useState } from 'react'
const [birds, setBirds] = useState([])
useEffect(() => {
fetch('/birds.json')
.then((response) => response.json())
.then((data) => setBirds(data))
}, [])useEffectは、「画面を描いたあとに、これもやっておいて」という指示です。引数は2つあります。
| 引数 | 意味 |
|---|---|
| 1つめ(関数) | 実行したい処理 |
| 2つめ(配列) | 依存配列。ここに書いた値が変わったときだけ、もう一度実行する |
[](空の配列)は「変わるものは何もない=最初の1回だけ」という意味になります。データを最初に1回読むだけなら、この形です。
読みこみ中の表示
データが届くまでの一瞬、birdsは空の配列です。何も出ないと壊れて見えるので、読みこみ中の状態を用意します。
const [isLoading, setIsLoading] = useState(true)
useEffect(() => {
fetch('/birds.json')
.then((response) => response.json())
.then((data) => {
setBirds(data)
setIsLoading(false)
})
}, [])
if (isLoading) {
return <p>よみこみ中…</p>
}前々回の早期returnがここで効きます。読みこみ中は一覧をまるごと描かず、短い文だけ返します。
開発中は2回実行される
コンソールを見ると、リクエストが2回飛んでいることがあります。壊れているのではなく、main.jsxにある<StrictMode>のしわざです。
Reactは開発中だけ、わざと「実行→片づけ→もう一度実行」をやります。片づけを書き忘れている効果(タイマーの止め忘れ、購読の解除し忘れ)をあぶり出すためです。
useEffect(() => {
const timer = setInterval(…)
return () => clearInterval(timer) // ← この片づけを書き忘れていないか
}, [])useEffectから関数を返すと、それが片づけとして呼ばれます。今回のfetchでは片づけを書いていませんが、本番のビルドでは1回しか実行されないので、このまま進めて問題ありません。
正直に:useEffectは最後の手段
ここまで書いておいてなんですが、公式は「Effectは必要ないことが多い」と繰り返し案内しています。
- 計算できるものはEffectで作らない——絞りこんだ結果や合計は、描画のたびに計算すればいい(前回やりました)
- イベントで起きることはイベントに書く——ボタンを押したときの処理をEffectで待ち構えない
- データ取得も、実務ではライブラリやフレームワークに任せることが多い——読みこみ中・失敗・再取得・キャッシュの扱いが、自前だとすぐ複雑になるため
useEffectの出番は、Reactの外側とやりとりするときです。今回のような小さな読みこみでは定番の書き方ですが、「困ったらuseEffect」と覚えないでください。
公式ドキュメントも見てみる
ja.react.dev外部サイトエフェクトを使って同期を行う – React公式の「エフェクトを使って同期を行う」。依存配列の書き方と、開発中に2回実行される理由がていねいに説明されています
ja.react.dev外部サイトそのエフェクトは不要かも – Reactそして「そのエフェクトは不要かも」。Effectを書きたくなったときに読むと、たいてい別の書き方が見つかりますこのレッスンのまとめ
public/に置いたファイルはそのままの名前で配信される(/birds.json)useEffect(処理, 依存配列)——描画のあとに実行する処理を書く[]は「最初の1回だけ」。第2引数を書き忘れると無限ループになる- 読みこみ中は
isLoadingと早期returnで別の画面を返す - 開発中に2回実行されるのはStrictModeの見張り。本番では1回
- Effectは最後の手段——計算で出せるものは計算、イベントの処理はイベントに書く
次は逆に、画面からデータを増やします。見つけた鳥をフォームから足せるようにする回です。
