React setState ne pas mettre à jour immédiatement
je travaille sur une application todo. C'est une version très simplifiée du code fautif. J'ai une case à cocher:
<p><input type="checkbox" name="area" checked={this.state.Pencil} onChange={this.checkPencil}/> Writing Item </p>
Voici la fonction qui appelle la case:
checkPencil(){
this.setState({
pencil:!this.state.pencil,
});
this.props.updateItem(this.state);
}
updateItem est une fonction qui est mappée à dispatch to redux
function mapDispatchToProps(dispatch){
return bindActionCreators({ updateItem}, dispatch);
}
mon problème est que lorsque j'appelle l'action updateItem et la console.journal de l'état, il est toujours de 1 pas en arrière. Si la case n'est pas cochée et pas vrai, j'ai toujours l'état de l'être vrai passé à la fonction updateItem. Dois-je appeler une autre fonction pour forcer l'état de mise à jour?
8 réponses
vous devriez invoquer votre seconde fonction comme un callback de setState, comme setsate se produit asynchrone. Quelque chose comme:
this.setState({pencil:!this.state.pencil}, myFunction)
cependant dans votre cas, puisque vous voulez que cette fonction soit appelée avec un paramètre, vous allez devoir être un peu plus créatif, et peut-être créer votre propre fonction qui appelle la fonction dans les accessoires:
myFunction = () => {
this.props.updateItem(this.state)
}
combinez ceux-ci ensemble et cela devrait fonctionner.
appel setState()
in React est asynchrone, pour diverses raisons (principalement la performance). Sous les couvertures Réagir lot de multiples appels à setState()
dans une mutation à un seul État, puis restituer le composant une seule fois, plutôt que de le restituer pour chaque changement d'état.
heureusement, la solution est assez simple - setState
accepte un paramètre de rappel:
checkPencil(){
this.setState({
pencil:!this.state.pencil,
}, function () {
this.props.updateItem(this.state);
}.bind(this));
}
lorsque vous mettez à jour votre état en utilisant une propriété de l'état actuel, la documentation React vous conseille d'utiliser la fonction Appel version de setState
au lieu de l'objet.
setState((state, props) => {...})
au lieu de setState(object)
.
La raison en est que setState
est plus une requête pour que l'état change qu'un changement immédiat. Réagir lots ceux setState
appels à l'amélioration de la performance.
ce qui signifie que la propriété de l'état que vous vérifiez pourrait ne pas être stable. C'est un écueil potentiel d'être conscient de.
Pour plus d'informations, voir la documentation ici: https://facebook.github.io/react/docs/react-component.html#setstate
pour répondre À votre question, je le ferais.
checkPencil(){
this.setState((prevState) => {
return {
pencil: !prevState.pencil
};
}, () => {
this.props.updateItem(this.state)
});
}
C'est parce que ça arrive de façon asynchrone, signifie donc que dans ce temps pourrait ne pas être mis à jour encore...
selon la documentation React v. 16, Vous devez utiliser une deuxième forme de setState()
qui accepte une fonction plutôt qu'un objet:
Les Mises À Jour Des États Peuvent Être Asynchrones
peut Réagir par lots de plusieurs setState() appels en une seule mise à jour pour performance.
parce que ça.des accessoires et de la ce.l'état peut être mis à jour en mode asynchrone, vous ne devrait pas compter sur leurs valeurs pour calculer l'état suivant.
Par exemple, ce code peut ne pas mettre à jour le compteur:
// Wrong
this.setState({
counter: this.state.counter + this.props.increment,
});
pour le corriger, utilisez une seconde forme de setState () qui accepte une fonction plutôt que d'un objet. Cette fonction recevra l'état précédent comme premier argument, et les accessoires au moment de la mise à jour est appliquée comme deuxième argument:
// Correct
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment
}));
j'ai utilisé les suggestions de rossipedia et de Ben Hare et j'ai fait ce qui suit:
checkPencil(){
this.setState({
pencil:!this.state.pencil,
}, this.updatingItem);
}
updatingItem(){
this.props.updateItem(this.state)
}
Ben a une excellente réponse pour la façon de résoudre le problème immédiat, mais je conseillerais aussi d'éviter de dupliquer l'état
si un État est dans redux, votre case à cocher devrait lire son propre état à partir d'un accessoire ou d'un magasin au lieu de garder une trace de l'état de vérification dans son propre composant et dans le magasin global
Faire quelque chose comme ceci:
<p>
<input
type="checkbox"
name="area" checked={this.props.isChecked}
onChange={this.props.onChange}
/>
Writing Item
</p>
La règle générale est que si vous trouvez qu'un État est nécessaire à plusieurs endroits, hissez-le à un parent (pas toujours redux) afin de maintenir l'avoir une seule source de vérité
essayez ceci
this.setState({inputvalue: e.target.value}, function () {
console.log(this.state.inputvalue);
this.showInputError(inputs[0].name);
});
fonction showInputError pour validation si vous utilisez des formulaires
d'abord définir votre valeur. après procéder vos travaux.
this.setState({inputvalue: e.target.value}, function () {
this._handleSubmit();
});
_handleSubmit() {
console.log(this.state.inputvalue);
//Do your action
}