🌐

React の State について

2024/04/14に公開

State とは

コンポーネント内にある変数の状態を管理するメモリーのこと。

例えば、テキストフィールドに入力した値がコンポーネント内で宣言したある変数に格納されるとき、
State内部(上で言っているメモリー)でその変数に今どんな値が入っているのか管理してくれる。

なぜ State を利用するのか

  1. コンポーネント内で宣言したローカルな変数の値が変わっても再レンダリングされなければ画面上に値は表示されない。
  2. 仮に再レンダリングが出来たとしてもローカルな変数の値はレンダリングの度に初期値に戻ってしまう。

1.コンポーネント内で宣言したローカルな変数の値が変わっても再レンダリングされなければ画面上に値は表示されない。

下記のコードは+1ボタンを押すとonClickイベントで用意したcountUp関数が走り、ローカル変数のcountが1ずつ足されるものである。ローカル変数の値が変わっていることが分かるように下にalertメソッドで値を表示するようにした。実際に押してみるとcountが1ずつ値が加算されているのに画面上の表示は変わっていない。変更したcountを表示させるためには再レンダリングをさせる必要がある。

2. 仮に再レンダリングが出来たとしてもローカルな変数の値はレンダリングの度に初期値に戻ってしまう。

上のコードでcountUpメソッドが実行された後にレンダリングが行われたと考えてみる。
renderメソッドが実行されるわけだが、そうするとローカル変数のcountはまた0で定義され直してしまうのでずっと回数が増えることはない。

つまりcountの値をある場所に保持し、レンダリングを跨いでその値を使えるようにしなければならない。その値を管理する場所というのがStateとなる。

State に値を保持し、その値を更新する

それでは実際にstateに値を保持し、その値を更新。さらに更新後にレンダリングを実行して画面上のカウントを更新してみる。
その役割を担ってくれるのがUseStateだ。
UseStateとはReactに組み込まれているフックと呼ばれるものでStateにアクセスできる機能を持つ。さらにStateに保持されている値を更新したとき再レンダリングを自動的に行なってくれる。

先ほどのコードにUseStateを使用して画面上のカウント表記も変えられるように修正した。

+1ボタンを押すと画面上のカウントも更新されているはずだ。
ボタンを押すとアラートが実行されるがExampleコンポーネントのトップ層に仕込んであるのでアラートの実行はレンダリングが行われていることを意味している。

useStateを使用しているのはこの部分。

let [count, setCount] = useState(0);

useStateの引数に渡されている値はcountの初期値で、返却されるのはcountsetCount
countstateに保持されている値で、setCountstateに保持されている値を読み取り、更新するためのメソッドだ。ボタンをクリック後にsetCountを用いてstate内部にあるcountを更新している。

setCount(count + 1);

1度のレンダリングで2度の更新を行うとどうなるか

let countUp = () => {
    setCount(count + 1);
    setCount(count + 1);
}

上記のようにボタンを押したときに実行される関数の中にsetCountメソッドを2つ仕込んでみる。
そうすると一見、1回の処理で2ずつ増えそうなものだが実際は1しか増えない。
つまりsetCountが実行された直後にstateの値を更新しに行くのではなく更新するのはレンダリング間ということになる。

とは言っても実際一度の処理でも2回メソッドを呼びたいケースもあるだろう。そんな時は下記のように書き換える。

let countUp = () => {
    setCount(count + 1);
    setCount(prev =>{
        return prev+1 // ※1
    });
}

※1 2回目のsetCountの引数に格納した関数ではretuen文を用いてしっかり値を返却すること。

UseState を使用した値更新とレンダリングの順序

  1. UseStateを使用してStateに値を保持。
  2. Onclickイベント実行。
  3. countUp関数実行開始。
  4. setCount(count + 1)の実行予約
  5. setCount(prev =>{ return prev+1 })の実行予約
  6. countUp関数実行終了。
  7. 予約していた4,5の処理を実行
  8. 再レンダリング。
  9. 反映。

Discussion