【React.js】useStateを使用しても再レンダリングされないときの対処法

  • 2023年5月5日
  • 2023年5月14日
  • React.js

こんにちは。

野中やすおです。

今回の記事でも、React.jsを扱っているときに遭遇するネタで「useStateを使用しても再レンダリングされない」時の対処方法について書きます。

事例

まずは具体例から。

上記の例では、カウント数の+ボタンを押してもカウントは+1されず、console.log上でも「再レンダリングされない・・・?」は一度しか表示されません。

つまり再レンダリングされず、画面が更新されていない状態です。

対処方法

対処方法としては、新しいオブジェントにコピーして、それをreturnすることで再レンダリングが行われるようになります。

console.log上でも「再レンダリングされる!」がボタンを押した回数分表示されるようになります。

ちなみにReact.jsの公式サイトでも、

This code modifies the object assigned to position from the previous render. But without using the state setting function, React has no idea that object has changed. So React does not do anything in response. It’s like trying to change the order after you’ve already eaten the meal. While mutating state can work in some cases, we don’t recommend it. You should treat the state value you have access to in a render as read-only.

To actually trigger a re-render in this case, create a new object and pass it to the state setting function:

The library for web and native user interfaces…

とオブジェクトのコピーを推奨しています。

同ページ上でもオブジェクトのコピーには、スプレッド構文(Spread syntax)などを使用することを勧めています。

You can use the … object spread syntax so that you don’t need to copy every property separately.

なぜ再レンダリングが行われないのか

Reactは、useStateなどのReact フック(Hooks)に「Object.is による比較アルゴリズムを使用している」ため、参照が同じ場合には、変更がないとみなされ、再レンダリングが行われません。

詳しくは、useStateページの注意事項(Caveats)に書いてあります。

If the new value you provide is identical to the current state, as determined by an Object.is comparison, React will skip re-rendering the component and its children. This is an optimization. Although in some cases React may still need to call your component before skipping the children, it shouldn’t affect your code.

The library for web and native user interfaces…

ちなみにObject.isのページは以下を参照してください。

both the same object (meaning both values reference the same object in memory)

MDN Web Docs

The Object.is() static method determines whether two values …

 

ということで、React.js使用時に「useStateを使用しても再レンダリングされない」時の対処方法でした。

新しいオブジェントにコピーして、それをreturnで返しましょう!