Day 4・useEffect と データ取得 — 外の世界とつながる
副作用とuseEffect — 描画のあとに動く処理
「画面を描くこと以外の処理」をどこに書くか。useEffectと依存配列の意味を、たとえで理解する。
副作用ってなに?
Reactのコンポーネントは、本来は「今の状態(state)を受け取って、画面(JSX)を返すだけ」の関数です。入力が同じなら出力も同じ、という素直な計算に近いものです。ところが実際のアプリでは、それだけでは足りません。サーバーにデータを取りに行ったり、タイマーを動かしたり、外部のイベントを購読したり、といった「画面を描くこと以外の処理」が必要になります。この、描画の外側で世界に触れる処理のことを副作用(effect)と呼びます。
たとえるなら、コンポーネントの本体は「注文票を見て料理の見た目を絵に描く」係です。でも実際にはお客さんの人数をお店に電話で問い合わせたり、タイマーをセットして焼き加減を測ったりもしたい。この「電話をかける」「タイマーをセットする」といった、絵を描くのとは別の外向きの行動が副作用です。これを絵を描いている最中にやると手が止まってしまうので、描き終わったあとにまとめてやろう、というのがuseEffectの発想です。
なぜ描画とは分けるのか
Reactは同じstateなら同じ画面になることを前提に、再描画のたびにコンポーネント関数を何度も呼び出します。もし関数の本体で直接fetchやタイマーを動かすと、描画のたびに通信が走ったり、動作が予測できなくなります。だから副作用は本体から追い出し、useEffectという専用の置き場所にまとめます。
useEffectの形
useEffectは「描画が終わったあとに、この処理を動かして」とReactにお願いする道具です。第一引数に動かしたい関数を、第二引数に依存配列(deps)という配列を渡します。この依存配列が、いつ再実行するかを決める心臓部です。
import { useEffect, useState } from "react";
function Clock() {
const [now, setNow] = useState(new Date());
useEffect(() => {
// 描画のあとに1秒ごとに現在時刻を更新する副作用
const id = setInterval(() => setNow(new Date()), 1000);
// 後片付け: このコンポーネントが消えるときにタイマーを止める
return () => clearInterval(id);
}, []);
return <p>{now.toLocaleTimeString()}</p>;
}依存配列 = いつ再実行するか
依存配列は「この中の値が前回と変わっていたら、もう一度副作用を実行してね」という指示リストです。Reactは再描画のたびに、配列の中身を前回と見比べます。何か変わっていれば副作用を動かし直し、すべて同じなら何もしません。だから配列に何を入れるかで、実行のタイミングが決まります。
- 依存配列なし → 毎回の描画のあとに実行される(使いどころは少ない)
- 空の配列 [] → 最初の描画のあと一度だけ実行される
- [url] のように値を入れる → その値が変わったときだけ再実行される
// userId が変わるたびに、そのユーザーのデータを取り直す
useEffect(() => {
fetch(`/api/users/${userId}`)
.then((r) => r.json())
.then(setUser);
}, [userId]);依存の入れ忘れに注意
副作用の中で使っている値(上の例のuserIdなど)は、原則すべて依存配列に入れます。入れ忘れると、値が変わっても副作用が古い値のまま動き続け、「別のユーザーを選んだのに前の人のデータが出る」といったバグになります。逆に空配列 [] は「本当に初回だけでいい」と確信できるときにだけ使いましょう。
AIにはこう聞く
「このuseEffectの依存配列はこれで正しいですか?中で使っている値を全部挙げて、入れ忘れがないか指摘してください」と聞くと、依存の抜けを洗い出せます。AIが生成したuseEffectも、依存配列だけは自分の目で確認するクセをつけましょう。
読んでも腑に落ちない所は、AIに噛み砕いてもらいましょう。
理解度チェック
答えられれば、面接で説明できる状態に一歩近づきます。
useEffectの第二引数に空の配列 [] を渡すと、副作用はいつ実行されますか?
副作用(effect)の説明として最も適切なものは?
依存配列(deps)が何を決めているのか、たとえを交えて説明してください。
記述式です。まず自分の言葉で答えを考えてから、模範解答を開いて自己採点してください。