si monthOffset = 12
, la condition est évaluée à true et met à jour l'état yearOffset
à 2017 si yearOffset = 2018
. Sur la base des documents de réaction et des autres réponses que j'ai lues, la fonction de rappel dans this.setState
se déclenche après la mise à jour de l'état. Pourtant, la fonction console.log()
affiche toujours 2018. J'ai essayé plusieurs méthodes d'implémentation de ce code en fonction du formulaire de réponses. d'autres questions connexes, mais la mienne ne fonctionne pas. Je ne sais pas pourquoi.
handleClick(e) {
const { monthOffset, yearOffset } = this.state
this.setState({ monthOffset: monthOffset - 1 })
if ( monthOffset - 1 === 11 ) { this.setState((prevState) => {
return { yearOffset: prevState.yearOffset - 1 } },
() => {console.log("yearOffset", yearOffset)}
)}
console.log("clicked")
}
Peut-être pourriez-vous simplifier votre logique de la manière suivante, afin d'éviter que plusieurs appels à setState
ne provoquent des résultats inattendus:
handleClick(e) {
const { monthOffset, yearOffset } = this.state
// call setState once
this.setState({
// Always decrement month offset
monthOffset : monthOffset - 1,
// Only decrement year offset if current month offset === 12
yearOffset : (monthOffset === 12) ? yearOffset - 1 : yearOffset
}, () => {
console.log("state updated to", this.state)
})
console.log("clicked")
}
La documentation indique que le rappel fonctionne toujours, mais je sais par expérience qu'il ne renvoie pas toujours ce que vous attendez. Je pense que cela a quelque chose à voir avec l'utilisation d'objets mutables à l'intérieur de l'état même.
Docs: https://reactjs.org/docs/react-component.html#setstate
Vous ne pouvez pas compter complètement sur le rappel. Au lieu de cela, vous pouvez créer
var stateObject = this.state
Apportez les modifications nécessaires à l'objet:
stateObject.monthOffset -= 1
puis définissez l'état comme ceci:
this.setState(stateObject);
De cette façon, vous avez une copie de la nextState
à l'intérieur de stateObject
Pour clarifier: Vous souhaitez effectuer toute l'évaluation avant de définir l'état, procédez comme suit:
monthOffset -= 1
alors if (monthOffset === 12) yearOffset -=1;
alors var stateObj = {monthOffset: monthOffset, yearOffset: yearOffset}
alors this.setState(stateObj);
Dans la documentation: "Le deuxième paramètre de
setState()
est une fonction de rappel facultative qui sera exécutée une fois que setState est terminé et que le composant est restitué. Généralement, nous recommandons d'utiliser ComponentDidUpdate () pour une telle logique . "
En gros, si vous voulez obtenir le prochain état, vous devez en avoir une copie dans votre fonction qui appelle setState()
ou vous devez obtenir le nextState
à partir de componentDidUpdate
Après: Tout ce que vous transmettez à setState()
en tant que paramètre est passé par référence (pas par valeur). Ainsi, si vous avez un objet SearchFilters: {}
dans votre état et dans votre appel à setState()
, vous avez
setState({SearchFilters: DEFAULT_SEARCH_FILTERS}); // do not do this
Vous avez peut-être défini SearchFilters
sur DEFAULT_SEARCH_FILTERS
dans le but d'effacer un formulaire appelé "Filtres de recherche", mais vous aurez en fait défini DEFAULT_SEARCH_FILTERS
(une constante) sur SearchFilters
, en effaçant votre DEFAULT_SEARCH_FILTERS
.
Comportement prévisible? À vous de me dire.
Il existe deux modèles courants pour appeler setState
dans React: objet setState
et "fonctionnel setState
" . La fonction setState est généralement utilisée lorsque l'état actuel (ou "état précédent", ou ce que vous souhaitez appeler l'ancien état) est appelé dans l'appel setState
. Ceci est fait parce que setState
est asynchrone et que, par conséquent, setStates
suivant peut parfois être exécuté avant que React n'ait réussi à terminer le premier cycle setState
.
Vous avez utilisé l'état existant dans votre appel setState
. Ce serait donc un endroit approprié pour utiliser la fonction setState
. Remplacer
this.setState({ monthOffset: monthOffset - 1 })
avec
this.setState(monthOffset => {return {monthOffset: monthOffset - 1}})
Si vous êtes comme moi la première fois que j'ai vu cela, vous vous dites peut-être: "Hein? Comment est-ce différent de ce que j'ai?" La différence est que lorsque setState
se voit attribuer une fonction au lieu d'un objet, il met la mise à jour en file d'attente au lieu de passer par son processus de résolution habituel, ce qui garantit que les opérations sont effectuées dans l'ordre.
Ou vous ne pensez peut-être pas cela; vous avez réellement utilisé setState
fonctionnel dans votre deuxième appel setState
. En l'utilisant dans votre premier aussi, vous vous assurez que les choses sont correctement placées dans la file d'attente.