React の状態更新が時々正しく動作しないのはなぜなのか疑問に思ったことはありますか?あるいは、ボタンを素早く複数回クリックしてもカウンターが期待どおりに更新されないのはなぜでしょうか?答えは、クロージャと React による状態更新の処理方法を理解することにあります。この記事では、すべてをピンとさせる簡単な例を使用して、これらの概念を解き明かします。
クロージャは、それが生まれた場所の小さな記憶を保持する関数であると考えてください。これは、関数が作成されたときに存在していたすべての変数のポラロイドのスナップショットのようなものです。単純なカウンターを使用してこれを実際に見てみましょう:
function createPhotoAlbum() { let photoCount = 0; // This is our "snapshot" variable function addPhoto() { photoCount += 1; // This function "remembers" photoCount console.log(`Photos in album: ${photoCount}`); } function getPhotoCount() { console.log(`Current photos: ${photoCount}`); } return { addPhoto, getPhotoCount }; } const myAlbum = createPhotoAlbum(); myAlbum.addPhoto(); // "Photos in album: 1" myAlbum.addPhoto(); // "Photos in album: 2" myAlbum.getPhotoCount() // "Current photos: 2"
この例では、addPhoto 関数と getPhotoCount 関数の両方が、createPhotoAlbum の実行が終了した後でも photoCount 変数を記憶しています。これは動作中のクロージャです - 関数はその誕生地を記憶しています!
React では、コンポーネントがその状態を記憶する方法においてクロージャが重要な役割を果たします。これは単純なカウンターコンポーネントです:
function Counter() { const [count, setCount] = useState(0); const increment = () => { // This function closes over 'count' setCount(count + 1); }; return ( <div> <p>Count: {count}</p> <button onClick={increment}>Add One</button> </div> ); }
インクリメント関数は、カウント状態変数の周囲にクロージャーを形成します。これは、ボタンがクリックされたときにどの番号を追加するかを「記憶」する方法です。
ここからが興味深いところです。クロージャが予期しない動作を引き起こす可能性がある状況を作成してみましょう:
function BuggyCounter() { const [count, setCount] = useState(0); const incrementThreeTimes = () => { // All these updates see the same 'count' value! setCount(count + 1); // count is 0 setCount(count + 1); // count is still 0 setCount(count + 1); // count is still 0! }; return ( <div> <p>Count: {count}</p> <button onClick={incrementThreeTimes}>Add Three</button> </div> ); }
このボタンをクリックすると、カウントが 3 増えると思われるかもしれませんが、驚きです。 1 しか増えません。これは「古いクロージャー」が原因です。関数は、作成時の count の元の値を参照してスタックしています。
数字の 0 が表示されたホワイトボードの写真を 3 枚撮り、それぞれの写真に 1 を加えようとするようなものだと考えてください。各写真にはまだ 0 が含まれています!
React はこの問題に対する洗練された解決策を提供します - 機能アップデート:
function FixedCounter() { const [count, setCount] = useState(0); const incrementThreeTimes = () => { // Each update builds on the previous one setCount(current => current + 1); // 0 -> 1 setCount(current => current + 1); // 1 -> 2 setCount(current => current + 1); // 2 -> 3 }; return ( <div> <p>Count: {count}</p> <button onClick={incrementThreeTimes}>Add Three</button> </div> ); }
クロージャーの値を使用する代わりに、React に「現在の値を取得してそれに 1 を追加する」ように指示します。それは、ホワイトボードに追加する前に常にホワイトボード上の現在の番号を確認する、親切なアシスタントがいるようなものです!
これが現実世界のシナリオ、つまりソーシャル メディア投稿の「いいね!」ボタンにどのように適用されるかを見てみましょう:
function createPhotoAlbum() { let photoCount = 0; // This is our "snapshot" variable function addPhoto() { photoCount += 1; // This function "remembers" photoCount console.log(`Photos in album: ${photoCount}`); } function getPhotoCount() { console.log(`Current photos: ${photoCount}`); } return { addPhoto, getPhotoCount }; } const myAlbum = createPhotoAlbum(); myAlbum.addPhoto(); // "Photos in album: 1" myAlbum.addPhoto(); // "Photos in album: 2" myAlbum.getPhotoCount() // "Current photos: 2"
覚えておいてください: 以前の値に基づいて状態を更新するときは、機能的な更新を優先してください。これは、記憶に基づいて作業するのではなく、変更を加える前に常に現在の値をチェックしてくれる信頼できるアシスタントがいるようなものです!
これらの概念を理解すれば、React での状態更新をプロのように処理できるようになります。コーディングを楽しんでください! ?
以上がクロージャに巻き込まれる: React 状態管理の癖を理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。