ReactのuseStateについてまとめてみた!
React最終更新:2024/12/15
今更ですが、Reactの勉強を始めました!
今回はState Hooksについて、公式ドキュメントで勉強したことをまとめていこうと思います。
https://react.dev/reference/react/hooks
勉強しながら書いたので、間違っているところがあったら教えていただけると嬉しいです。
情報を記憶する「State Hooks」
まず初めに、State Hooksってどんなときに使うんでしょうか?
というかそもそもState Hooksって何?
ナニモワカラン。
公式ドキュメントでは下記のように説明されていました。
状態により、コンポーネントはユーザー入力などの情報を「記憶」できます。たとえば、フォーム コンポーネントは状態を使用して入力値を保存し、画像ギャラリー コンポーネントは状態を使用して選択した画像インデックスを保存できます。
うーん...あまりピンとこないです...
とりあえず情報を記憶するために使用するものであること、フォームの入力値を保存する用途などに用いることだけ理解しました。
State Hooksは2種類存在する
State Hooksとして使用できるHooksは下記の2つです。
違いは状態変数の更新方法にあるようです。
- useState:直接更新することが可能。
- useReducer:リデューサー関数内の更新ロジックを使用して、状態変数を更新する。
これだけ見るとuseStateの方がシンプルで良さそうな気がします!
しかし、実際に手を動かしてみないと分からないので、それぞれについてもう少し詳しく調べてみます。
useState
基本の使い方
コンポーネントの最上位レベルでuseStateを呼び出すことで、使うことができます。
import { useState } from 'react';
function MyComponent() {
const [hoge, setHoge] = useState(1);
// ...
戻り値を格納する変数は、配列の分割を使って[hoge, setHoge]
のようにするのが慣例らしいです。
パラメータ
useStateを呼び出す際、引数を渡すことで状態変数の初期値を設定することができます。
この引数は最初のレンダリング時のみ有効で、それ以降は無視されます。
引数には具体的な値の他に、関数を渡すこともできます。
関数を渡した場合、その関数は初期化関数として扱われます。
初期化関数はコンポーネントを初期化するときに呼び出され、その戻り値が初期状態になるようです。
import { useState } from 'react';
function MyComponent() {
// 初期値はnumberの28
const [age, setAge] = useState(28);
// 文字列を初期値として渡すことも可能です
const [name, setName] = useState('Taylor');
// 初期化関数は引数をとらず、任意の型の値を返す必要があります
// また、公式ドキュメントには、純粋関数であるべきと書かれていました
const [todos, setTodos] = useState(() => createTodos());
// ...
一口メモ:純粋関数とは
純粋関数とは以下の2点の条件を両方とも満たす関数のことです。
- 副作用が発生しないこと
- 引数が同じ場合、何回呼び出しても同じ結果を返すこと(参照透過性とも言うらしい)
戻り値
useStateは2つの戻り値を返します。
- 状態変数
- 状態変数の値を更新し、再レンダリングをトリガーできるset関数
だから戻り値を格納する変数を[hoge, setHoge]
のようにするんですね!
注意点
公式のドキュメントでは、下記の3点が注意点として記載されていました。
- useStateはフックなので、コンポーネントまたは独自フックの最上位レベルでしか呼び出せない。そのため、繰り返しや条件分岐の処理の中で呼び出すことはできない。
- Strict Modeでは、Reactは偶発的な不純物を見つけるために初期化関数を2回呼び出す。初期化関数は純粋関数であるべきで、純粋関数である場合動作に影響はない。また、2回呼び出したうちのどちらかの呼び出しの結果は無視される。
- 初期化関数を2回呼び出す処理は開発環境のみの動作であり、本番環境の動作には影響しない。
set関数の使い方
set関数を使うと状態を更新し、再レンダリングをトリガーできます。
set関数には値を直接渡すか、現在の状態から次の状態を計算する関数を渡すことができます。
const [name, setName] = useState('Edward');
const [age, setAge] = useState(20);
function handleClick() {
// 値を直接渡す
setName('Taylor');
// 現在の状態から次の状態を計算する関数を渡す
setAge(a => a + 1);
// ...
set関数の注意点
- set関数を呼び出して状態を変更した後、1回目の状態変数の読み取り時は更新前の古い値が読み取られる。
- 指定した新しい値がObject.isの比較によって現在の状態と同じと判断された場合、Reactはコンポーネントとその子要素の再レンダリングをスキップする。(最適化のため)