0
0

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 の値を直接書き換えると再レンダリングされる?

Posted at

結論

setData を使わずに data を直接書き換えても 「React的な意味での再レンダリングは起きません」
data の値が変わったらレンダリングされる」のではなく、setData が呼ばれたときに再レンダリングがスケジュールされる」 という仕組みです。

なぜ setData を通さないとダメか

useState は内部的に「前回の state 値」を React がどこかに保持しています。

const [data, setData] = useState(initial) で受け取る data は、そのレンダリング時点の 「スナップショット(snapshot)」 でしかありません。

data.xxx = 123 のように直接ミューテート(mutation)しても、React に「state が変わった」という通知は届かないため、再レンダリングは走りません。

❌ ダメな例(直接ミューテーション)

const [data, setData] = useState({ count: 0 });

const bad = () => {
  data.count = data.count + 1;   // 直接変更
  // setData を呼んでいないので、この時点では画面は変わらない
};

この場合、console.log(data.count)1 になりますが、コンポーネントは再レンダリングされないので画面表示は更新されません。


✅ 正しい更新パターン(新しい参照を作って setData

オブジェクトや配列の場合、新しいオブジェクト/配列を作り直して setData に渡す必要があります。

const increment = () => {
  setData(prev => ({
    ...prev,
    count: prev.count + 1,
  }));
};

setData が呼ばれることで React が「state が変わった」と判断し、再レンダリングがスケジュールされます。

「参照(reference)が変わった」ことがトリガーになるので、ミューテーションではなく新しい値を渡すのがポイントです。

例外的に「変わったように見える」ケース

data がオブジェクトで、そのプロパティを直接書き換えたあとに 他の原因(親の再レンダリングなど) で再レンダリングが起きた場合、たまたまその変更が反映されることがあります。

これは「React が変化を検知して再レンダリングした」のではなく、
「たまたま別要因で再レンダリングされたときに、ミューテート済みのオブジェクトを読んだ」だけです。

まとめ(押さえるべき認識)

✅ 正しい理解

  • setData を呼んだら再レンダリングされる」

❌ 誤解しがち

  • data の中身を変えたら(直接代入しても)レンダリングされる」
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?