1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

CodexでTODOアプリなどを作りながら、Reactの機能を一つずつ整理しています。
今回は、useState の使い方と状態更新の仕組みについて、備忘録としてまとめます。

構文

useState は、コンポーネント内で状態(State)を管理するためのHookです。

const [状態, 状態を変更する関数] = useState(初期値);

TODOアプリでは、たとえば次のように定義できます。

const [todos, setTodos] = useState<Todo[]>([]);

この場合、todos には初期値として空の配列が入ります。
状態を更新したいときは、todos を直接変更するのではなく、setTodos を呼び出します。

更新関数の書き方

状態を更新する方法には、大きく2つのパターンがあります。
更新後の値をどのように決めるかによって使い分けます。

1. 新しい値を直接渡す

setTodos([
  {
    id: "1",
    text: "買い物",
    completed: false,
  },
]);

この書き方では、setTodos に新しい配列を渡して、todos を更新します。

更新後の値がすでに決まっている場合に適しています。

2. 現在の値をもとに更新する

setTodos((currentTodos) => [
  ...currentTodos,
  newTodo,
]);

この書き方では、現在の状態を引数として受け取り、その値をもとに次の状態を返します。
上記の例では、既存のTODOリストを展開し、末尾に newTodo を追加しています。

前の状態をもとに次の状態を作る場合は、こちらの書き方を使うと安全です。
複数の状態更新がまとめて処理される場面でも、最新の状態をもとに更新できます。

Stateはどのように更新されるのか

const [todos, setTodos] = useState<Todo[]>([]);

todosconst で定義されています。そのため、「値を更新してよいのだろうか」と疑問に思いました。

しかし、実際には次のように todos を直接再代入しているわけではありません。

todos = ...

状態を変更するときは、必ず setTodos を呼び出します。

setTodos((currentTodos) => [
  ...currentTodos,
  newTodo,
]);

setTodos を呼ぶと、Reactは次回のレンダーで使用するStateを更新します。その後、コンポーネント関数が再び実行されます。

再実行されたコンポーネント内では、useState がReact内部で保持している最新のStateを返すため、todos には更新後の値が入ります。

つまり、todos 自体を書き換えているのではなく、レンダーのたびに新しい todos が定義されているというイメージです。

Stateの値は、そのレンダー時点の「スナップショット」です。

setTodos を呼び出しても、現在実行中の処理にある todos の値がその場で変わるわけではありません。
次回のレンダーで、更新後の値を受け取ります。

最後に

useState を整理することで、Stateの更新は単純な変数の書き換えではなく、Reactによる再レンダーの仕組みとセットで成り立っていることを理解できました。

特に、以下の点を意識して使っていきたいです。

Stateは直接変更せず、更新関数を使う
前のStateをもとに更新する場合は、関数形式で書く
Stateの値は、レンダー時点のスナップショットとして扱う

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?