Reace Hooks その②

Next.js-2.React Hooks編-

useStateでテキスト入力

useStateを使って入力したテキストがリアルタイムで表示されるようにしてみましょう。

まずはapp/componentsフォルダにtextInput.jsを作成しTextInputコンポーネントを定義します。

"use client";

import { useState } from "react";

export default function TextInput() {
    const [text, setText] = useState("");

    return (
        <div>
            <input
                type="text"
                value={text}
                onChange={(e) => setText(e.target.value)}
            />
            <p>You typed: {text}</p>
        </div>
    );
}

次にapp/page.jsでTextInputコンポーネントを呼び出して表示します。

import TextInput from "./components/textInput";
<TextInput />

入力フォームに入力したテキストがリアルタイムで「You tiped:」の箇所に反映されます。

コード解説

textInput.jsのコードを解説していきます。

クライアントコンポーネントの宣言、useStateのインポートをします。

"use client";

import { useState } from "react";

textを更新するための設定をします。初期値は空テキスト「””」です。

 const [text, setText] = useState("");

inputタグのonChangeイベントでtextの更新処理ができるように記述しています。

  return (
        <div>
            <input
                type="text"
                value={text}
                onChange={(e) => setText(e.target.value)}
            />
            <p>You typed: {text}</p>
        </div>
    );

見慣れない記述かと思いますが、ここでのイベントハンドラはアロー関数により定義されているので、下記のように定義したのと同じ意味になります。

 function handleChange(e) {
        setText(e.target.value);
    }

    return (
        <div>
            <input 
                type="text"
                value={text}
                onChange={handleChange} 
            />
            <p>You typed: {text}</p>
        </div>

アロー関数は「式」なのでJSX内に値としてそのまま埋め込めるというわけです。

useStateでクラスのON・OFF

次に、CSSとJavascriptを組み合わせて見た目を変化させる時によく使うクラスのON・OFFのやり方を見ていきましょう。

まずはapp/componentsフォルダに「toggleButton.js」ファイルを作成し、下記コードを記述します。

"use client";

import { useState } from "react";
import "./styles.css"; // CSSファイルを適用

export default function ToggleButton() {
    // 初期状態は OFF(false)
    const [isActive, setIsActive] = useState(false);

    // アロー関数で ON / OFF を切り替える
    const toggleActive = () => setIsActive(prev => !prev);

    return (
        <button
            className={isActive ? "active" : ""}
            onClick={toggleActive}
        >
            {isActive ? "Active" : "Inactive"}
        </button>
    );
}

次にapp/componentsフォルダに「sytle.css」を作成して下記コードを記述します。

button {
    padding: 10px 20px;
    font-size: 16px;
    border: none;
    cursor: pointer;
    background-color: lightgray;
    transition: 0.3s;
}

button.active {
    background-color: dodgerblue;
    color: white;
}

最後にapp/page.jsでToggleButtonコンポーネントを呼び出します。

下記のようにInactiveボタンをクリックするとスタイルがあたります。

コード解説

toggleButton.jsのコードを解説していきます。

  • クライアントコンポーネントの宣言
  • useStateのインポート
  • style.cssの読み込み
"use client";

import { useState } from "react";
import "./styles.css";

isActiveを更新する設定をします。初期値は「false」です。

const [isActive, setIsActive] = useState(false);

イベントハンドラーtoggleActiveを定義します。

const toggleActive = () => setIsActive(prev => !prev);

見慣れない記述がありますが、これは関数型更新と呼ばれる書き方です。
説明が長くなるので説明は後述します。

JSX内ではbuttonタグがクリックされる度にisActiveがtureとfalseで反転する記述を書いています。

return (
        <button
            className={isActive ? "active" : ""}
            onClick={toggleActive}
        >
            {isActive ? "Active" : "Inactive"}
        </button>
    );

クラスはReactでは「class」ではなく「className」と書きます。

{isActive ? "active" : ""}
{isActive ? "Active" : "Inactive"}

この記述は2つとも「三項演算子」です。

isActiveの値が「true」か「false」かによって返す値を分けています。

三項演算子は「式」なのでJSX内に値として{}の中に入れられます。

関数型更新

関数型更新とは?

初期値ではisActiveは「false」で、「!」は値を反転させる記号なので、!isActiveは「true」となります。
一度クリックするとisActiveは「true」に更新されて、!isActiveは「false」ということになります。
このように記述することでクリックする度にtrueとfalseが反転する処理を記述しています。

このように常に最新のstateの値を基にした処理を書きたいときにこの関数型更新を使用します。

「常に最新のstateの値」とはどういうことか?

例えば下記のようなコードを書いたとします。

function Counter() {
    const [count, setCount] = useState(0);

    function handleClick() {
        setCount(count + 1);
        setCount(count + 1);
        setCount(count + 1);
    }

    return (
        <div>
            <p>Count: {count}</p>
            <button onClick={handleClick}>+3</button>
        </div>
    );
}

このコードだとbuttonタグをクリックする度に「3ずつ」数字が増えそうなものですが、実際は「1ずつ」しか増えません。
これはuseStateが非同期で動くからなのですが、なぜそうなるのかの詳細な説明は省きます。

上記の奥に「3ずつ」増やしたい場合は下記のように記述します。

function Counter() {
    const [count, setCount] = useState(0);

    function handleClick() {
        setCount(prev => prev + 1);
        setCount(prev => prev + 1);
        setCount(prev => prev + 1);
    }

    return (
        <div>
            <p>Count: {count}</p>
            <button onClick={handleClick}>+3</button>
        </div>
    );
}

このように記述することでhandleClick関数の処理の中でcountの値が関数型更新により順番に1ずつ加算され、最終的に一回のクリックで「3ずつ」増えます。

次回はuseStateで配列を更新する手順を見ていきましょう。

コメント

タイトルとURLをコピーしました