2
votes

Comment réparer HandleToggleState?

J'ai une simple bascule Material-ui dans mon composant de réaction. Je veux l'utiliser pour basculer l'état (faux / vrai). Si je commence par useState (false) la première fois que je clique sur la bascule, cela indique false plutôt que true.

Je me demande si un autre hook de réaction résoudrait ce problème. useEffect, useCallback ...

const Component = () => {
  const [toggleValue, setToggleValue] = useState(false);

  const handleToggleChange = () => {
    setToggleValue(!toggleValue);
    console.log("toggle value in handle: " + toggleValue);
  };


  return(
    <FormControlLabel
       control={
          <Switch
             checked={toggleValue}
             onChange={handleToggleChange}
             value="my toggle"
          />
       }
    />
  );
};

Je m'attendrais à ce que setPreseason (! preseason); définisse l'état opposé à ce qu'il est actuellement. Vrai à faux et faux à vrai.

C'est probablement le cas, mais lorsque j'enregistre l'état sur la ligne suivante, il enregistre l'état initial et enregistrera toujours le contraire de ce qu'est la bascule.


2 commentaires

C'est parce que le programme de mise à jour d'état est asynchrone


Comment puis-je y remédier? Le hook useEffect ou useCallback fonctionnera-t-il? Si oui, à quoi ressemblerait le code?


3 Réponses :


0
votes

Vous le faites correctement, sauf que toggleValue est juste une variable locale et n'est pas modifiée simplement en appelant setToggleValue (l'état sera changé, mais cela se produit de manière asynchrone ).

Vous pouvez faire quelque chose comme ceci à la place:

const handleToggleValue = () => {
  const newToggleValue = !toggleValue;
  setToggleValue(newToggleValue);
  console.log('toggleValue: ' + newToggleValue);
}

Cela dépend de votre intention avec la nouvelle valeur de bascule. Cela corrige simplement ce que vous faisiez avec l'appel console.log. Mais vous pouvez rencontrer d'autres problèmes après cela, étant donné que vous utilisez la nouvelle valeur de bascule avant que l'état ne soit mis à jour. Mais c'est pour une autre question SO ...


2 commentaires

Cela n'a pas fonctionné pour moi. Il enregistre toujours la valeur initiale.


Il est probablement préférable d'utiliser l'exemple useEffect; mais voici un codepen pour montrer comment cela fonctionne (pas sûr de ce que vous faisiez différemment, mais la console enregistre l'état actuel de la case à cocher lorsque vous la basculez).



1
votes

La fonction de mise à jour de l'état renvoyée par useState est asynchrone

Si vous devez réagir aux changements d ' état useEffect est l'endroit pour cela

const Component = () => {
  const [toggleValue, setToggleValue] = useState(false);

  const handleToggleValue = () => {
    setToggleValue(!toggleValue);
  };

  useEffect(() => {
    console.log("toggleValue: " + toggleValue);
      // second argument to useEffect is an array of dependencies
      // this function is going to run every time one of the dependencies
      // changes
  }, [toggleValue])

  return (
    <FormControlLabel
      control={
        <Switch
          checked={toggleValue}
          onChange={handleToggleValue}
          value="my toggle"
        />
      }
    />
  );
}


7 commentaires

J'ai déjà vu des exemples comme celui-ci en ligne et je ne comprends pas comment cela s'intègre dans mon code actuel. Où setToggleValue est-il défini et comment cela fonctionne-t-il avec handleToggleValue?


@sbaden a mis à jour ma réponse à votre composant, dans handleToggleValue vous venez de mettre à jour state et à l'intérieur de useEffect vous fournissez une fonction à exécuter à chaque fois toggleValue changements


J'ai changé mon code pour refléter ce que vous avez ci-dessus et j'obtiens le même résultat. Comment useEffect change-t-il quelque chose?


@sbaden Comment est-ce pareil? sandbox il enregistre d'abord false lorsque le composant se monte, puis enregistre le contraire à chaque changement d ' état


J'ai mis à jour votre bac à sable pour ajouter un journal de console supplémentaire pour illustrer ce que je veux dire. codesandbox.io/s/reverent-heyrovsky-4kq9e


Je pense avoir omis un détail important ... J'essaie de faire quelque chose avec le nouveau toggleValue après avoir définiToggleValue dans le handleToggleValue. Est-ce que je mettrais plutôt cette fonctionnalité dans useEffect?


@sbaden Oui, chaque fois que vous avez besoin de faire quelque chose lorsque les changements de state le placent dans useEffect et n'oubliez pas d'ajouter les dépendances



1
votes

Le problème est de savoir quelle valeur toggleValue se trouve à l'intérieur de la fermeture. N'est-ce pas ce que vous attendez. Passez plutôt un rappel à setToggleValue . Vous récupérerez l'état actuel, que vous pourrez ensuite modifier.

const handleToggleValue = () => {
  setToggleValue((toggleValue) => !toggleValue);
}


4 commentaires

Cela n'a pas fonctionné pour moi. Il enregistre toujours la valeur initiale


vous mettez cette instruction de journal de console en dehors du rappel, et à l'intérieur de la fonction de rendu, n'est-ce pas? pouvez-vous partager plus de code?


Je n'ai actuellement pas de rappel et je ne sais pas comment le formater. J'ai essayé de simplifier le code que je partageais mais je peux vous en donner plus - Comment dois-je le partager avec vous?


ajoutez-le dans votre question initiale; le code tel qu'il est devrait fonctionner correctement, l'erreur est ailleurs