1

useState関数を使用してオブジェクトを更新する、次の簡単な例を考えてみましょう。

App.tsx

import { useState } from 'react';

export default function App() {

  const [state, setState] = useState({
    id: 0,
  });

  const update = () => {

    setState(prev => {
      const id = Date.now();
      console.log('previous id:', prev.id, 'new id:', id);
      return {
        id,
      };
    });

  };

  return (
    <div>
      <div>state: {JSON.stringify(state)}</div>
      <button onClick={update}>Update</button>
    </div>
  );
}

これを標準の create-react-app typescript テンプレート (React 17.0.2 を使用) に入れ、アプリを開発モードで実行します。更新ボタンをクリックし続け、コンソールを観察します。すぐに、意図した状態と実際の状態の間に矛盾が生じるでしょう。

previous id:  1636301326090  new id:  1636301326260
previous id:  1636301326260  new id:  1636301326440
previous id:  1636301326440  new id: *1636301326611*
previous id: *1636301326612* new id:  1636301326804  // What???
previous id:  1636301326804  new id:  1636301326997

上記のコンソール ログではid: 1636301326612、状態が設定されていたため、状態がどこからともなく出てきましたid: 1636301326611

まだ見知らぬ人ですが、アプリが本番用にビルドされている場合、これを再現できません。また、機能の更新を忘れsetStateて、コメントアウトされたコードのようにオブジェクトを渡すだけの場合 (原子性の要件のために、実際のおもちゃではないコードでは実行できません)、問題も存在しないようです。

私は完全に途方に暮れています。setStateどういうわけか間違って使用していますか?

必要に応じて、完全なサンプル リポジトリを提供できます。

4

1 に答える 1