ReactのuseEffect()の動作を確認してみる

前回はuseRef()でしたが、今回はその続きです。

useEffect()の第二引数を調べてみました。
引数なし、空の配列、要素一つの配列の3通りで試しました。

作業内容は

  • Clickボタンを2回おす
  • Let's Unmountを押す
  • Let's Mountを押す
  • Clickボタンを2回押す

引数を指定しない

import { useEffect, useState } from "react";

const Item = () =>
{
    const [counter, setCounter] = useState(0);

    useEffect(() => {
        console.log(`Effect: ${counter}`);

        return () =>
        {
            console.log(`Cleanup: ${counter}`);
        }
    });

    return (
        <div>
            <input type="button" value="Click" onClick={e => setCounter(counter + 1) } />
        </div>
    )
}

const App = () =>
{
    const [flag, setFlag] = useState(true);

    return (
        <>
            <div>
                <input type="button" value={flag ? "Let's Unmount" : "Let's Mount"} onClick={e => setFlag(!flag)} />
            </div>

            {
                flag && <Item />
            }
        </>
    )
}

export default App;

どのようにログが表示されるかというと、

// 開いた瞬間
Effect: 0 

// ボタン1回クリック
Cleanup: 0 
Effect: 1 

// ボタン2回目クリック
Cleanup: 1 
Effect: 2 

// Let's Unmount
Cleanup: 2 

// Let's Mount
Effect: 0 

// ボタン1回クリック
Cleanup: 0 
Effect: 1 

// ボタン2回目クリック
Cleanup: 1 
Effect: 2 

開いた瞬間(マウント時)にEffect: 0が実行されます。
アンマウントされた時にCleanup: 2が実行されます。

useEffect()の第一引数は、関数を返すと次のエフェクト実行前とアンマウント時にそれを実行することが出来ます。

よーく見るとEffectとCleanupのタイミングが分かります。
次の例はマウント時/アンマウント時だけエフェクトを実行します。

空の配列

useEffect(() => {
    console.log(`Effect: ${counter}`);

    return () =>
    {
        console.log(`Cleanup: ${counter}`);
    }
}, []);

前回のuseEffect()の第二引数に空の配列を指定しました。

// 開いた瞬間
Effect: 0 

// ボタン1回クリック

// ボタン2回目クリック

// Let's Unmount
Cleanup: 0

// Let's Mount
Effect: 0 

// ボタン1回クリック

// ボタン2回目クリック

Clickボタンを押しても無反応です。
マウント時のEffect: 0と、アンマウント時のCleanup: 0だけが表示されます。

引数を指定する

今回は状態を一つ(flag)を追加しました。
マウント時、アンマウント時は前の例と同じですが、配列に追加された状態に変更があった時だけエフェクトが実行されます。

const Item = () =>
{
    const [counter, setCounter] = useState(0);
    const [flag, setFlag] = useState(false);

    useEffect(() => {
        console.log(`Effect: ${counter}`);

        return () =>
        {
            console.log(`Cleanup: ${counter}`);
        }
    }, [counter]);

    return (
        <div>
            <input type="button" value="Click Counter" onClick={e => setCounter(counter + 1) } />
            <input type="button" value="Click Flag" onClick={e => setFlag(!flag)} />
        </div>
    )
}

例えば、Click Counterボタンが押された時だけエフェクトが実行されます。
もし配列を[counter, flag]にするとどちらのボタンを押してもエフェクトが実行されます。
もし配列を[flag]にするとClick Flagボタンが押された時だけエフェクトが実行されます。

前回のレンダリング時と配列の構成が変化した際にエフェクトが実行されるわけですね。

実行結果を載せておきます。

BlockEditor certificate css DataGrid Docker Gutenberg Hyper-V iframe MUI openssl PHP React ReduxToolkit REST ubuntu WordPress オレオレ認証局 フレームワーク