React学習ちまちま開始。
自分向けの備忘録。

Stateの基本

import { useState } from "react";

const Example = () => {
// [State値を格納する変数、 Stateを更新するための関数]
// 更新関数はStateの状態を更新するために使用
  let [val, setVal] = useState();

  return (
    <>
      <input
        type="text"
        // 入力値をsetVal()へ渡しvalを更新
        onChange={(e) => {
          setVal(e.target.value);
        }}
      />
      = {val}
    </>
  );
};

export default Example;

useStateの実行すると、React内部と接続し、状態の管理がされるようになる。
[現在の値、更新関数]が配列となって返却される。
更新関数に新たな値を渡し→State値を更新→コンポーネントを再実行。

State値は非同期で更新される

import { useState } from "react";

const Example = () => {
  const [count, setCount] = useState(0);
  const countUp = () => {
  // 2回呼び出されるが、どちらも初期値0を使用しているため結果は1となる
    setCount(count + 1);
    setCount(count + 1);
  };
  return (
    <>
      <p>現在のカウント数: {count}</p>
      <button onClick={countUp}>+</button>
    </>
  );
};

export default Example;

カウンターを例に考える。
更新関数を2回呼んでみるが、count値は2とはならない。
Stateに新しい値が反映されるのはイベントハンドラーを終えたあとのため。

常に新しい値を使用したい場合は更新関数に関数型の引数を渡す。↓

import { useState } from "react";

const Example = () => {
  const [count, setCount] = useState(0);
  const countUp = () => {
    setCount(count + 1);
   // 前回更新された1が入ってくるため、結果は2となる
    setCount(prevstate => prevstate + 1);
  };
  return (
    <>
      <p>現在のカウント数: {count}</p>
      <button onClick={countUp}>+</button>
    </>
  );
};

export default Example;

オブジェクトを扱う際の注意点

オブジェクトのステートを変更する場合には新しいオブジェクトを渡してあげる必要がある。

import { useState } from "react";

const Example = () => {
  const personObj = { name: "Tom", age: 18 };
  const [person, setPerson] = useState(personObj);
  const changeName = (e) => {
   // 渡す値は新しく生成したオブジェクトでないといけないため、下記の書き方だと値が変わったと認識されず動かない。
    // person.name = e.target.value;
    // setPerson(person);

  // スプレッド構文を使用し、変更したプロパティのみ上書き
    setPerson({ ...person, name: e.target.value });
  };
  const changeAge = (e) => {
    setPerson({ ...person, age: e.target.value });
  };
  const reset = () => {
    setPerson({ name: "", age: "" });
  };

  return (
    <>
      <h3>Name: {person.name}</h3>
      <h3>Age: {person.age}</h3>
      <input type="text" value={person.name} onChange={changeName} />
      <input type="number" value={person.age} onChange={changeAge} />
      <button onClick={reset}>リセット</button>
    </>
  );
};

export default Example;

配列を扱う際の注意点

オブジェクト同様、新しい配列を渡してあげる必要がある。

import { useState } from "react";

const Example = () => {
  const numArray = [1, 2, 3, 4, 5];
  const [nums, setNums] = useState(numArray);
  const shuffle = () => {
  // 下記だとうまくいかない、スプレッド構文で配列を展開して新しい配列として渡してあげる必要がある
  // const newNums = nums

    const newNums = [...nums];
    const value = newNums.pop();
    newNums.unshift(value);
    setNums(newNums);
  };
  return (
    <>
      <h1>{nums}</h1>
      <button onClick={shuffle}>shuffle</button>
    </>
  );
};

export default Example;

stateをpropsで渡すケース

・コンポーネントが消滅する可能性があるとき
(一度消滅したコンポーネントのstateの値はリセットされるため、保持したい場合は親コンポーネントで定義)
・特定のstateを複数の子コンポーネントで共有したい時

import { useState } from "react";

const Example = () => {
  const [toggle, setToggle] = useState(0);
  const [countA, setCountA] = useState(0);
  const [countB, setCountB] = useState(0);
  const toggleComponent = () => {
    setToggle((prev) => !prev);
  };
  return (
    <>
     // トグルボタンによって表示非表示を設定。非表示にした際にリセットさせずに値を保持させておきたい
      <button onClick={toggleComponent}>toggle</button>
      {toggle ? (
        <Count key="A" title="A" count={countA} setCount={setCountA} />
      ) : (
        <Count key="B" title="B" count={countB} setCount={setCountB} />
      )}
    </>
  );
};

const Count = ({ count, title, setCount }) => {
  const countUp = () => {
    setCount(count + 1);
  };
  const countDown = () => {
    setCount(count - 1);
  };
  return (
    <>
      <p>
        {title}: {count}
      </p>
      <button onClick={countUp}>+</button>
      <button onClick={countDown}>-</button>
    </>
  );
};

export default Example;

【参考】
・Udemy:【2024年最新】React(v18)完全入門ガイド
・React実践入門

c.sakyou

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA