Maison >interface Web >js tutoriel >Pris dans une fermeture : comprendre les bizarreries de la gestion de l'état de React

Pris dans une fermeture : comprendre les bizarreries de la gestion de l'état de React

DDD
DDDoriginal
2025-01-13 20:29:45483parcourir

Caught in a Closure: Understanding Quirks in React State Management

TLDR

  • Les fermetures sont comme des sacs à dos que les fonctions transportent, contenant des données datant de leur création
  • Les composants React utilisent des fermetures pour mémoriser leur état et leurs accessoires
  • Les fermetures obsolètes peuvent entraîner des bugs lorsque les mises à jour d'état ne fonctionnent pas comme prévu
  • Les mises à jour fonctionnelles fournissent une solution fiable pour travailler avec le dernier état

Introduction

Vous êtes-vous déjà demandé pourquoi parfois vos mises à jour d'état React ne fonctionnent pas correctement ? Ou pourquoi cliquer plusieurs fois rapidement sur un bouton ne met pas à jour le compteur comme prévu ? La réponse réside dans la compréhension des fermetures et de la manière dont React gère les mises à jour d'état. Dans cet article, nous dévoilerons ces concepts à l'aide d'exemples simples qui feront que tout s'enclenchera.

Qu’est-ce qu’une fermeture ?

Considérez une fermeture comme une fonction qui garde un petit souvenir de son lieu de naissance. C'est comme un instantané polaroïd de toutes les variables qui existaient lors de la création de la fonction. Voyons cela en action avec un simple compteur :

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"

Dans cet exemple, les fonctions addPhoto et getPhotoCount mémorisent la variable photoCount, même après la fin de l'exécution de createPhotoAlbum. Il s'agit d'une fermeture en action - des fonctions se souvenant de leur lieu de naissance !

Pourquoi les fermetures sont importantes dans React

Dans React, les fermetures jouent un rôle crucial dans la façon dont les composants se souviennent de leur état. Voici un composant de compteur simple :

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>
    );
}

La fonction d'incrémentation forme une fermeture autour de la variable d'état de comptage. C'est ainsi qu'il « se souvient » du numéro auquel ajouter lorsque l'on clique sur le bouton.

Le problème : les fermetures obsolètes

C'est ici que les choses deviennent intéressantes. Créons une situation où les fermetures peuvent provoquer un comportement inattendu :

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>
    );
}

Si vous cliquez sur ce bouton, vous pourriez vous attendre à ce que le nombre augmente de 3. Mais surprise ! Il n'augmente que de 1. Cela est dû à une "fermeture obsolète" - notre fonction est bloquée en regardant la valeur d'origine de count lors de sa création.

Pensez-y comme si vous preniez trois photos d'un tableau blanc affichant le chiffre 0, puis essayez d'ajouter 1 à chaque photo. Vous aurez toujours 0 sur chaque photo !

La solution : mises à jour fonctionnelles

React fournit une solution élégante à ce problème - mises à jour fonctionnelles :

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>
    );
}

Au lieu d'utiliser la valeur de notre fermeture, nous disons maintenant à React "prenez la valeur actuelle et ajoutez-y une". C'est comme avoir un assistant utile qui regarde toujours le numéro actuel sur le tableau blanc avant de l'ajouter !

Exemple concret : bouton J'aime sur les réseaux sociaux

Voyons comment cela s'applique à un scénario réel : le bouton J'aime d'une publication sur les réseaux sociaux :

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"

Conclusion

Points clés à retenir

  1. Les Les fermetures sont des fonctions qui mémorisent les variables à partir desquelles elles ont été créées - comme les fonctions avec mémoire.
  2. Les Fermetures obsolètes se produisent lorsque votre fonction utilise des valeurs obsolètes de sa mémoire au lieu des valeurs actuelles.
  3. Mises à jour fonctionnelles dans React (setCount(count => count 1)) garantissent que vous travaillez toujours avec l'état le plus récent.

Rappel : lors de la mise à jour de l'état en fonction de sa valeur précédente, privilégiez les mises à jour fonctionnelles. C'est comme avoir un assistant fiable qui vérifie toujours la valeur actuelle avant d'apporter des modifications, plutôt que de travailler de mémoire !

Meilleures pratiques

  • Utiliser les mises à jour fonctionnelles lorsque le nouvel état dépend de l'état précédent
  • Soyez particulièrement prudent avec les fermetures dans les opérations asynchrones et les gestionnaires d'événements
  • En cas de doute, console.connectez vos valeurs pour vérifier les fermetures périmées
  • Envisagez d'utiliser React DevTools pour déboguer les mises à jour d'état

Avec ces concepts à votre actif, vous êtes bien équipé pour gérer les mises à jour d'état dans React comme un pro ! Bon codage ! ?

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn