🍯

【React超入門】大雑把な人が理解するためのuseState

2021/09/30に公開

どんな人向けか

React始めようと公式を読んだけど、いまいちしっくり来ない。
props? state?状態管理?Reactフックってなに?
とりあえず概要をざっくり理解して使ってみたい。

という方向けに、できるだけ聞きなれた言葉で説明しようした記事です。
ですので、厳密に言うと異なることがあるかもしません。実際に使って慣れてきた後に、正しい情報を公式で再度読んでみてください。

Reactフック(Hooks)とは

フック (Hooks) は React 16.8 で追加された新機能です。
以下は React 公式ページの「フックの導入」及び「フック早わかり」からの抜粋です。

要するにフックとは?
フックとは、関数コンポーネントに state やライフサイクルといった React の機能を “接続する (hook into)” ための関数です。フックは React をクラスなしに使うための機能ですので、クラス内では機能しません。

簡単に言うと、ReactフックはReactの機能を使用するための専用の関数です。
独自の方法で書く必要があり、書き方は後ほど解説します。

以前は、stateはクラスコンポーネントでしか使えなかったようですが、今は関数コンポーネントで使えるようになり記述量も減りました。
基本的に今後は関数コンポーネントでReactフックを作成してください。
ではReactで管理するstateとは何でしょう?

stateとは

stateとは関数コンポーネントが持つことが出来る「状態」です。

「状態」という言葉がよく出てきますが、要するに画面やアプリケーション上で使用する「値」のことを指しており、プログラミングにおける変数と思ってもらっていいです。
stateは「値を持っておく箱」であり、値を入れたり書き換えたり「管理」できます。
例えば、アコーディオンコンポーネントで考えた時、アコーディオンが開いているのか閉じているのかという状態を持っておくのがstateです。

Reactではその「state(状態)」を操作するのにフックを使うのですが、そこで最も利用されるのがuseState()です。

useState()の書き方

Reactの変数であるstateは独自の方法で書かないといけません。
以下がuseState()の基本構文です。

const [状態変数、状態を変更するための関数] = useState(状態の初期値)

状態変数、状態を変更するための関数には任意の名前をつけることができます。

const [count、setCount] = useState(0)

これがuseState()の宣言の仕方です。
JavaScriptでいう、let count = 0と同じです。

以下解説

  • count ・・・countの状態を持たせている変数/現在の値
  • setCount・・・count状態を保存するための関数。関数の名前は、setXxxxのようにstate変数の名前の前に set を付けます。
  • 0・・・上記countには初期値を入れる必要があります。現在countには0が入っています。

基本的な使い方は、現在のstate(count)を参照するのと、setCount()の引数に値を入れてstateの中身を更新します。
さっそく使ってみましょう。

使用例

下記は公式ドキュメントの例です。
ボタンをクリックすると、カウンターの値が増えるコンポーネントです。

function Example() {
  // useState を呼び出して state 変数を宣言して初期値をセット
  // 状態変数countの初期値は0
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

クリックするたびにsetCountで、count(現在の値)+1に更新されていきます。
更新された現在の値が、countに表示されます。

注意すべきReactフックのルール

こうして見るとただの変数と関数なのですが、setStateを使用する上でいくつかルールがあります。
他にもありますが、代表的なものを紹介します。

stateの更新は必ずsetStateを使う

stateの値を更新するのに、通常の変数のように直接count = 0などでの変更はできません。
Reactはstateの変更を検知して再レンダリングを行うので、直接変更しても変更は検知されず画面の再レンダリングもされません。

function Example() {
    const [count, setCount] = useState(0);
    const handleClick = () => {
   // これはできません
        count ++;
    };
    
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => handleClick()}>
        Click me
      </button>
    </div>

フックはトップレベルのみで呼び出す

ループや条件分岐内でsetStateを宣言することはできません。
場合によってフックの順番や実行回数が変わると、レンダーされた時に状態を正しく保持できなくなるためです。
公式ドキュメント:フックのルール

function Example() {
  // これはできません
  if (isEnabled) {
    const [count, setCount] = useState(0);
    }
・・・

stateはsetStateで更新しても即座に書き変わるわけではない

setState の呼び出しは非同期です。setStatestate を更新したからといって直後に state を参照しても新しい値は反映されていません。
もし関数内で現在の state に基づいた操作をする必要がある場合は注意が必要です。

function Example() {
    const [count, setCount] = useState(0);
    const handleClick = () => {
        setCount(count + 1);
	// ここではまだcountの値は変わっていません。
	console.log(count)
    };
    
・・・

まとめ

  • ReactフックはReactの機能を使用するための専用の関数で、最もよく使われるのがsetStateである
  • stateとは関数コンポーネントが持つことが出来る「状態」でプログラミングにおける変数
  • statesetStateを使用するときの主な注意点3つ

以上です。読んでいただきありがとうございました。

Discussion