6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

useStateに関して学んだこと

Last updated at Posted at 2024-09-27

背景

こんにちは。エンジニアのKennieです。
最近フロントエンドの勉強をし始めてuseStateについて学びました。
公式ドキュメントを読みながら勉強していこうと思い、そこでuseStateについて学んだことを書いてみました!

1. Reactのstateは非同期で更新される

React のstateの更新は非同期で行われます。つまり、stateを更新するために下記のように setAge を呼び出しても、その時点で即座に変更されるわけではありません。実際の更新は、次のレンダーサイクルまで待たなければなりません。

以下の例では、年齢 (age) を1ずつ増やすボタンのクリックイベントを扱います。

const [age, setAge] = useState(42);

function handleClick() {
  setAge(age + 1); 
  setAge(age + 1); 
  setAge(age + 1); 

  return (
    <div>
      <p>Current age: {age}</p>
      <button onClick={handleClick}>Increase Age</button>
    </div>
  );
}

↑こちらのコードの動き
https://codesandbox.io/p/sandbox/react-dev-forked-x58vzm?file=%2Fsrc%2FApp.js%3A5%2C1

このコードでは、ボタンを1回押すと、最終的に age は43になります。なぜなら、すべての setAge(age + 1) は、最初の age の値(42)を基に計算されるからです。これは上記に書いたReactの非同期性によるもので、setAge を呼び出しても、再レンダーされるまで age の値は更新されないためです。

アップデータ関数を使った更新


function handleClick() {
  setAge(preveAge => preveAge + 1); // setAge(42 => 43)
  setAge(preveAge => preveAge + 1); // setAge(43 => 44)
  setAge(preveAge => preveAge + 1); // setAge(44 => 45)
}

↑こちらのコードの動き
https://codesandbox.io/p/sandbox/react-dev-forked-mg6zxk?file=%2Fsrc%2FApp.js%3A9%2C32

setAgeの呼び出しが、最新のageの値を基にして次の値を計算するため、ボタンを1回押すとageは3回増加し、最終的に+3されます。たとえば、ageが最初に42であれば、1回のクリックで45になります。このように、アップデータ関数を使用すれば前の値を基に新しい値を計算するため、意図通りの結果が得られます。

2. stateの更新におけるオブジェクトと配列

Reactでは、stateにオブジェクトや配列を使用することができますが、既存のオブジェクトを直接変更すべきではないとされています。具体的な例を用いて、その理由を説明します。

こちらは既存のオブジェクトを直接変更している例

const [userProfile, setUserProfile] = useState({ username: '', email: '' });
userProfile.username = 'Kennie'; 

こちらは置き換えをしている例

setUserProfile({
  ...userProfile,
  username: 'Kennie'
});

解説

  1. 既存のオブジェクトを直接変更している場合: Reactではstateにある既存のオブジェクトを直接変更するとReactはその変更を検知できません。結果として、Reactが再レンダリングされたとき、username の値は 'Kennie' ではなく、依然として空の文字列 '' のままです。
  2. 新しいオブジェクトの作成: スプレッド構文(...userProfile)を使用することで、元のuserProfileオブジェクトのプロパティをコピーし、新しいオブジェクトを作成します。この新しいオブジェクトは、元のものとは異なるメモリ領域に保存されるため、参照が変わり、Reactはstateの変更を正しく検知できるようになります。

参考リンク

あとがき

公式ドキュメントにはuseStateの様々な使い方が書かれていて、将来的にここで得た情報は開発をしている際、もしくはバグに出くわした際、役立ってくると感じました。

6
5
1

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
6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?