Voici le problème: j'essaie d'appeler 2 fonctions en cliquant sur un bouton. Les deux fonctions mettent à jour l'état (j'utilise le hook useState). La première fonction met correctement à jour value1 en 'new 1', mais après 1s (setTimeout) la deuxième fonction se déclenche, et elle change la valeur 2 en 'new 2' MAIS! Il a remis la valeur1 à «1». Pourquoi cela arrive-t-il? Merci d'avance!
import React, { useState } from "react";
const Test = () => {
const [state, setState] = useState({
value1: "1",
value2: "2"
});
const changeValue1 = () => {
setState({ ...state, value1: "new 1" });
};
const changeValue2 = () => {
setState({ ...state, value2: "new 2" });
};
return (
<>
<button
onClick={() => {
changeValue1();
setTimeout(changeValue2, 1000);
}}
>
CHANGE BOTH
</button>
<h1>{state.value1}</h1>
<h1>{state.value2}</h1>
</>
);
};
export default Test;
javascript
reactjs
react-hooks
Bartek
la source
la source
changeValue2
?useState
ou de l'utiliser à la placeuseReducer
.const [state, ...]
, puis en y faisant référence dans le setter ... Il utilisera le même état tout le temps.useState
appels distincts , un pour chaque "variable".Réponses:
Bienvenue dans l'enfer de la fermeture . Ce problème se produit car chaque fois qu'il
setState
est appelé,state
obtient une nouvelle référence de mémoire, mais les fonctionschangeValue1
etchangeValue2
, en raison de la fermeture, conservent l'anciennestate
référence initiale .Une solution pour garantir le
setState
fromchangeValue1
etchangeValue2
obtenir le dernier état consiste à utiliser un rappel (ayant l'état précédent comme paramètre):Vous pouvez trouver une discussion plus large sur ce problème de fermeture ici et ici .
la source
Vos fonctions devraient être comme ceci:
Ainsi, vous vous assurez de ne manquer aucune propriété existante dans l'état actuel en utilisant l'état précédent lorsque l'action est déclenchée. Ainsi vous évitez ainsi d'avoir à gérer les fermetures.
la source
Lorsque
changeValue2
est invoqué, l'état initial est maintenu afin que l'état revienne à l'état initial et que lavalue2
propriété soit écrite.La prochaine fois
changeValue2
est invoquée après cela, elle détient l'état{value1: "1", value2: "new 2"}
, donc lavalue1
propriété est écrasée.Vous avez besoin d'une fonction de flèche pour le
setState
paramètre.la source
Ce qui se passe, c'est que les deux
changeValue1
etchangeValue2
voient l'état du rendu dans lequel ils ont été créés , donc quand votre composant rend pour la première fois ces 2 fonctions voient:Lorsque vous cliquez sur le bouton,
changeValue1
est appelé en premier et change l'état{value1: "new1", value2: "2"}
comme prévu.Maintenant, après 1 seconde,
changeValue2
est appelée, mais cette fonction voit toujours l'état initial ({value1; "1", value2: "2"}
), donc quand cette fonction met à jour l'état de cette façon:setState({ ...state, value2: "new 2" });
on finit par voir:
{value1; "1", value2: "new2"}
.la source
la source