こう 聞かれます
- 「useEffect の
依存配列は 何の ために ありますか」 - 「依存配列を
空に した とき、 省いた とき、 値を 入れた ときの違いは」 - 「useEffect で return する
関数は 何ですか。 いつ呼ばれますか」
面接官が 見ている点
- useEffect は
「描画の あとに、 React の 外の 物と 同期する」 ための 物だ、 と言えるか - 依存配列の 3 つの
書き方の 違いを、 いつ 動くかで言えるか - 後片付けが、
次の 実行の 前と アンマウントの ときに 呼ばれると 分かっているか - 依存配列から
値を 抜いて 警告を 黙らせると、 古い値を 使う 不具合に なると 知っているか
短い答え
- useEffect は、
描画の あと (多くは 画面に 反映された あと ) に、 タイマー、 イベントの 購読、 外部への 接続など、 React の 外の 物と 同期する 処理を 書く 場所です。 - 依存配列に
書いた 値が 前回と 変わった ときだけ、 処理を やり直します。 空の 配列なら 最初に 表示された ときだけ、 配列を 省くと 毎回の 描画の あとに 動きます。 - 処理から
返した 関数が 後片付けで、 次に やり直す前と、 部品が 画面から 消える ときに 呼ばれます。 タイマーの 解除や 購読の 取り消しを ここに 書きます。
この
少し 詳しい答え
基本の形
TypeScript (JSX)
function Clock() {
const [now, setNow] = useState(new Date());
useEffect(() => {
// 同期を始める
const id = setInterval(() => setNow(new Date()), 1000);
// 後片付け
return () => clearInterval(id);
}, []); // 最初の表示のときだけ始める
return <p>{now.toLocaleTimeString()}</p>;
}後片付けが
依存配列の 3 つの書き方
| 書き方 | 動くとき |
|---|---|
| 配列を省く | 毎回の |
| [] | 最初に |
| [roomId] | 最初と、 |
値が
値が 変わった ときの流れ
チャットの
- 新しい roomId で描き直す
- 前の
処理の 後片付けを 呼ぶ ("a" から切断) - 新しい
値で 処理を 動かす ("b" に接続)
TypeScript (JSX)
useEffect(() => {
const connection = createConnection(roomId);
connection.connect();
return () => connection.disconnect();
}, [roomId]);「始める」と
依存配列は 「自分で 選ぶ物」ではない
処理の
よく ある間違い
- 後片付けを書かない
タイマーや 購読が 残って 処理を 続け、 画面を 行き来する たびに 増えていきます - linter の
警告を 消すために 依存配列から値を抜く 古い値を 使い続けます。 使う 値を 減らす方向で直します - 依存配列に
入れた state を、 同じ Effect の 中で set する 変わる、 動く、 また 変わる、と 描き直しが 止まらなくなります。 計算できる 値なら 描画の 中で 計算し、 Effect では set しません - ボタンを
押した ときの 処理を useEffect に書く 押したことが きっかけなら、 イベントの 処理の 中に書きます
深掘りの問い
- 「開発中だけ useEffect が 2 回動くのはなぜ」 Strict Mode が、
後片付けの 書き忘れを 見つける ために、 接続、 切断、 接続を 1 回多く 試すから、と答えます - 「useEffect で
データを 取る ときの注意は」応答が 順番どおりに 来るとは 限らないので、 後片付けで 古い 応答を 捨てる、と答えます - 「useEffect が
要らない場面は」 props や state から 計算できる値、 ボタンを 押した ときの 処理は、 useEffect を 使わずに 書ける、と答えます
