こんにちはフロントエンドエンジニアのまさにょんです!
今回は、ReactのHooksである useEffectの使い方や、発火タイミング・メリットについて解説していきます。
目次
useEffectとは?
useEffectとは、コンポーネントの画面生成後または、更新後に自動実行する関数処理を設定するHooksです。
基本的には、設定した第1引数の関数処理が、コンポーネントが画面に描写された後や更新されたら実行されます。
このコンポーネントの画面生成(画面レンダリング)や更新が、useEffectを理解するためのポイントです。
Reactでは、コンポーネントが画面の構成パーツとしてレンダリングされます。
また、stateやpropsの変更は検知されて、その変更は即時反映されます。
そういったコンポーネントのレンダリング(画面生成)や部分的な再レンダリング(再生成)でuseEffectは動きます。
useEffectの構文・使い方は?
useEffectの構文は、次のとおりです。
useEffect( コールバック関数, [ 監視する値(依存関係の値)の配列 ] );
第1引数にコールバック関数、第2引数は任意で配列を設定できます。
第2引数の配列内の値によって、useEffectの第1引数に渡したコールバック関数の実行タイミングが変化します。
この実行タイミングの変化が、useEffectのポイントです。
次の useEffect の SampleCodeでは、4パターンの useEffect を使っています。
ポイントは、第1引数に設定したコールバック関数の実行タイミングを第2引数によって制御している点です。
useEffect の発火タイミングについては、別途、解説します。
import { useState, useEffect } from 'react';
const containerStyle = {
textAlign: "center",
};
const buttonStyle = {
margin: "20px"
};
export const UseEffectSample = ()=>{
const [count, setCount] = useState(0);
const [count2, setCount2] = useState(0);
// 1. 第2引数なし: Component の生成後や state 変更の度に呼び出される
useEffect(() => {
console.log('Component の生成後や state 変更の度に呼び出される useEffect()');
});
// 2. 第2引数・空配列: Component の生成後に1度だけ呼び出される
useEffect(() => {
console.log('Component の生成後に1度だけ呼び出される useEffect()');
}, []);
// 3. 第2引数の count の変更を監視している
useEffect(()=>{
console.log('Robotama を監視している useEffect() が実行されました');
},[count]);
// 4. 第2引数の count2 の変更を監視している
useEffect(()=>{
console.log('Gunmar を監視している useEffect() が実行されました');
},[count2]);
useEffect(()=>{
console.log('--------------------- 1回分のレンダリング完了 --------------------------');
});
return (
<div style={containerStyle}>
<h1>useEffect-Sample</h1>
<h2>Robotama-Counter: { count }</h2>
<h2>Gunmar-Counter: { count2 }</h2>
<button onClick={() => setCount(count + 1)} style={buttonStyle}>Robotama +</button>
<button onClick={() => setCount2(count2 + 1)} style={buttonStyle}>Gunmar +</button>
</div>
);
};
最初の画面レンダリング後
最初の画面レンダリング後は、コンポーネント内のすべての useEffect のコールバック関数が実行されているのがわかります。
このように、useEffectでは、コンポーネントが画面にマウントされた後(画面にレンダリング後)に必ずコールバック関数が実行されます。
監視しているstateの変更による再レンダリング後 Ver. count
「 Robotama + 」ボタンをClickすると、count という stateが更新されます。
すると、countを監視している useEffect とコンポーネントが生成・更新されたら起動する useEffect の2つのコールバック関数が実行されます。
監視しているstateの変更による再レンダリング後 Ver. count2
「 Gunmar + 」ボタンをClickすると、count2 という stateが更新されます。
すると、count2を監視している useEffect とコンポーネントが生成・更新されたら起動する useEffect の2つのコールバック関数が実行されます。
useEffectの発火タイミングは?
ここまでの解説で useEffectの使い方や実行タイミングは、わかってきたと思いますが、ここでまとめておきます。
useEffect の発動タイミングは、useEffect を設定したコンポーネントの「最初の画面レンダリング後」か
「state・props 変更等による再レンダリング後」の2パターンになります。
ポイントは、第1引数に設定したコールバック関数の実行タイミングを第2引数によって制御できる点です。
useEffectの発火タイミングまとめ
useEffectの発火タイミングを簡単にまとめると、次のようになります。
- 第2引数なし: Component の生成後や state・props の変更の度にコールバック関数が発火する
- 第2引数が空配列: Component の生成後に1度だけコールバック関数が発火する
- 第2引数あり: 監視対象の変更の度にコールバック関数が発火する
注意してほしいのは、Componentが画面にマウントされた後(画面にレンダリング後)に必ずコールバック関数が実行されるという点です。
ただ、初回のレンダリング後にだけコールバック関数を実行するようにしたり、監視する対象を設定して、その値の変更があった時だけコールバック関数を実行するなど・・・
コールバック関数の実行タイミングを調整できる点が、useEffectのポイントです。
第2引数なし: Component の生成後や state・props の変更の度にコールバック関数が発火する
// 1. 第2引数なし: Component の生成後や state 変更の度に設定した関数実行
useEffect(() => {
console.log('Component の生成後や state 変更の度に呼び出される useEffect()');
});
第2引数が空配列: Component の生成後に1度だけコールバック関数が発火する
第2引数を[]
(空配列) にすることで、コンポーネントの更新によるuseEffectの停止をすることができます。
// 2. 第2引数が空配列: Component の生成後に1度だけ設定した関数実行
useEffect(() => {
console.log('Component の生成後に1度だけ呼び出される useEffect()');
}, []);
第2引数あり: 監視stateの変更の度にコールバック関数が発火する
const [count, setCount] = useState(0);
const [count2, setCount2] = useState(0);
// 1. 第2引数の count の変更を監視している
useEffect(()=>{
console.log('count を監視している useEffect() が実行されました');
},[count]);
// 2. 第2引数の count2 の変更を監視している
useEffect(()=>{
console.log('count2 を監視している useEffect() が実行されました');
},[count2]);
useEffectの使い方と注意点・まとめ
ここまで出ててきた、useEffect の使い方と注意点をまとめていきます。
- コンポーネントが画面にレンダリング(生成)されたり、部分的に再生成されたら設定した関数を実行します。
- 第2引数によって、コールバック関数の実行タイミングを調整できます。
- useEffect は、1つのコンポーネント内で複数使用することができます。
- useEffect内で、stateの更新関数を実行してしまうと「無限ループ」が発生するので注意です。
1番注意すべきなのは、useState の更新関数を useEffect 内で実行してしまうことです。
コンポーネント内の state の変更を検知してしまう useEffect 内で、stateの更新を実行すると、
その変更を検知して useEffect が起動して、また state を更新して、また useEffect が起動して・・・
このように「無限state更新」と「無限useEffect」(無限ループ)が発生するので、useEffect の中で基本的に state の更新関数を実行しないようにしましょう。
ただし、第2引数で特定の state を監視して、その監視 state 以外の stateを更新するのは無限ループが起こりません。
useEffect に対するよくある Q & A
useEffectのメリットとは?
関数処理の実行タイミングを制御できる点が、useEffect のメリットです。
特定の値が更新された時だけ処理を行うように設定したり、コンポーネントの初回作成時だけ処理を実行するようにしたりなどの実行タイミング制御ができます。
なぜAPIとの通信で、useEffectが使われるのですか?
APIとの通信で、1回だけデータを取得する必要があるものは、
コンポーネントの初回の生成(レンダリング)後のタイミングで取得すればちょうどいいので、よく使用されるのだと思います。
useEffectは、どんな時に使うのか?
コンポーネントが画面にレンダリングされたタイミングや、特定の値が変更されたタイミングで特定の処理を実行したいときに使います。
Twitterやってます!Follow Me!
神聖グンマー帝国の逆襲🔥
神聖グンマー帝国の科学は、世界一ぃぃぃぃぃぃ!!!!!