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.
3 Réponses :
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 ...
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).
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" /> } /> ); }
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
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); }
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
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?