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
どういうわけか間違って使用していますか?
必要に応じて、完全なサンプル リポジトリを提供できます。