この記事ではReactフックの1つである『useState』について、
useState
とはuseState
の構文useState
の使い方
などをサンプルコードを用いて分かりやすく説明するように心掛けています。ご参考になれば幸いです。
useStateとは
useState
は、関数コンポーネント内で状態管理を可能にするReactフックの一つです。useState
を用いれば、関数コンポーネントでもクラスコンポーネントのように状態(state)を持たせることができるようになり、関数コンポーネントが内部で保持する状態(state)の保持と更新を行うことができます。
補足
useState
は最も利用されているReactフックです。useState
はReact16.8で導入されたフックです。- stateはpropsと違って後から変更することが可能です。
useStateの構文
useState
の構文を以下に示します。useState
は初期値initialState
を引数に取り、配列を返します。この配列は現在の状態state
とその状態を更新するための関数setState
を含んでいます。
useStateの構文
const [state, setState] = useState(initialState);
initialState
- 状態(state)の初期値です。この値は関数コンポーネントが最初にマウントされる時に使用されます。
state
- 状態(state)を保持する変数です。
- 現在の状態(state)の値を示します。
setState
関数でのみ状態(state)の値を更新することができます。
setState
- 状態(state)を更新するための関数です。
- この関数に新しい状態(state)の値を渡すことで、状態(state)が更新され、コンポーネントが再レンダリングされます。
状態(state)の更新はsetState
関数によってのみ行われます(State
の箇所はコードによって異なります)。以下に示す方法で状態(state)を更新することができます。
// setState関数の引数に「直接値」を渡す方法
// 例
setState(0); // 数値を渡している
setState(state + 1); // 計算式の結果を渡している
setState(nextState); // 変数に格納されている値を渡している
// setState関数の引数に「関数」を渡す方法
// 例
setState((state) => state + 1);
setState((state) => getNextState(state));
setState
関数の引数に「関数」を渡した場合、現在の状態に基づいて次の状態を計算しています(後ほど詳しく解説します)。
また、状態(state)の初期値はuseState
の引数で設定します。以下に示す方法で状態(state)を更新することができます。
// useStateの引数に「直接値」を渡す方法
// 例
useState(0); // 数値を渡している
useState(initialState + 1); // 計算式の結果を渡している
useState(initialState); // 変数に格納されている値を渡している
// useStateの引数に「関数」を渡す方法(関数の返り値が初期値になる)
// 例
useState(() => createInitialState());
補足
状態(state)を保持する変数xxxxx
に対して、その状態(state)を更新する関数はsetXxxxx
と命名するのが基本です。後ほど説明するサンプルコードでは、状態(state)を保持する変数count
に対して、その状態(state)を更新する関数はsetCount
と命名しています。
useStateの使い方
以下に示しているのはuseState
を用いた簡単なカウンターアプリのサンプルコードです。このサンプルコードを元にuseState
の使い方を説明します。
import React, { useState } from 'react';
function App() {
const [count, setCount] = useState(0); // 0はカウントの初期値
const onButtonClick = () => {
setCount(count + 1);
};
return (
<>
<p>カウント回数: {count}</p>
<button onClick={onButtonClick}>カウント</button>
</>
);
}
export default App;
まず、上記のサンプルコードの以下の箇所では、useState
をインポートしています。useState
はインポートしなくても使えますが、インポートしない場合には、useState()
をReact.useState()
にする必要があります。
import React, { useState } from 'react';
上記のサンプルコードの以下の箇所では、useState
を使用してcount
という状態と、それを更新するsetCount
関数を作成しています。また、count
は0で初期化しています。
const [count, setCount] = useState(0);
上記のサンプルコードの以下の箇所では、変数count
の値を取得しています。
<p>カウント回数: {count}</p>
上記のサンプルコードの以下の箇所では、ボタンがクリックした際に、onButtonClick
関数が呼ばれており、そのonButtonClick
関数の中ではsetCount
関数を呼び出しています。setCount
関数を呼び出されると、変数count
が1増加します。
const onButtonClick = () => {
setCount(count + 1);
};
実行結果
補足
上記のサンプルコードにおいて、setCount(count + 1)
をsetCount(count++)
にしても正常に動作せず、ページに正しく反映されません。状態(state)を直接操作することはReactの管理外になっています。そもそも上記のサンプルコードでは、変数count
をconst宣言しているので、「++」演算子による操作は定数の規約違反になります。
useStateの注意点
useState
を用いる上での注意点を以下に示します。
- 状態(state)は非同期に更新されるので注意
上記の注意点についてこれから説明します。
状態(state)は非同期に更新されるので注意
先ほど示したカウンターアプリでは、状態(state)の更新は以下の2つの方法で行うことができます。
// useStateで作成したsetCount関数の引数に「直接値」を渡す方法
setCount(count + 1)
// useStateで作成したsetCount関数の引数に「関数」を渡す方法
setCount((count) => count + 1);
上記の方法において、setCount
関数を複数呼び出した場合の動作に違いがあるので注意してください。以下のサンプルコードでは、先ほど示したカウンターアプリにて、setCount(count + 1)
を2回呼び出すようにしました。
import React, { useState } from 'react';
function App() {
const [count, setCount] = useState(0);
const onButtonClick = () => {
setCount(count + 1);
setCount(count + 1); // ★setCount関数を2回呼び出している
};
return (
<>
<p>カウント回数: {count}</p>
<button onClick={onButtonClick}>カウント</button>
</>
);
}
export default App;
上記のサンプルコードではsetCount(count + 1)
を2回呼び出しているのですが、カウントボタンを押しても+1しかされません。それは、Reactでは状態(state)を非同期に更新しているからです。具体的には、状態(state)が更新されるのは、イベントハンドラー(クリック等のイベントによって呼び出されるコードや関数のこと)の実行完了後であり、状態(state)がコンポーネントの再描画までに変更されることはありません。そのため、1回目のsetCount(count + 1)
と2回目のsetCount(count + 1)
の間では、状態(ここではcount
)の値は変化しないのです。
一方、以下のサンプルコードでは、setCount((count) => count + 1)
を2回呼び出しています。
import React, { useState } from 'react';
function App() {
const [count, setCount] = useState(0);
const onButtonClick = () => {
setCount((count) => count + 1);
setCount((count) => count + 1); // ★setCount関数を2回呼び出している
};
return (
<>
<p>カウント回数: {count}</p>
<button onClick={onButtonClick}>カウント</button>
</>
);
}
export default App;
setCount((count) => count + 1)
のように、useState
で作成したsetCount
関数の引数に「関数」を渡すと、先ほどの問題が解決されます。setCount
関数の引数に「関数」を渡した場合、現在の状態に基づいて次の状態を計算しています。そのため、setCount((count) => count + 1)
を2回呼び出した場合、+2されます。
一般的には、useState
で作成する関数(ここではsetCount
関数)の引数に「関数」を渡す方がバグが起きにくく、安全で確実に状態を更新できるのでお勧めです。
本記事のまとめ
この記事ではReactフックの1つである『useState』について、以下の内容を説明しました。
useState
とはuseState
の構文useState
の使い方
お読み頂きありがとうございました。