Je voudrais demander pourquoi mon état ne change pas quand je fais un événement onclick. Il y a quelque temps, j'ai recherché la nécessité de lier la fonction onclick dans le constructeur, mais l'état n'est pas mis à jour. Voici mon code:
import React from 'react';
import Grid from 'react-bootstrap/lib/Grid';
import Row from 'react-bootstrap/lib/Row';
import Col from 'react-bootstrap/lib/Col';
import BoardAddModal from 'components/board/BoardAddModal.jsx';
import style from 'styles/boarditem.css';
class BoardAdd extends React.Component {
constructor(props){
super(props);
this.state = {
boardAddModalShow: false
}
this.openAddBoardModal = this.openAddBoardModal.bind(this);
}
openAddBoardModal(){
this.setState({ boardAddModalShow: true });
// After setting a new state it still return a false value
console.log(this.state.boardAddModalShow);
}
render() {
return (
<Col lg={3}>
<a href="javascript:;" className={style.boardItemAdd} onClick={this.openAddBoardModal}>
<div className={[style.boardItemContainer,style.boardItemGray].join(' ')}>
Create New Board
</div>
</a>
</Col>
)
}
}
export default BoardAdd
Ce rappel est vraiment compliqué. Il suffit d'utiliser async wait à la place:
async openAddBoardModal(){
await this.setState({ boardAddModalShow: true });
console.log(this.state.boardAddModalShow);
}
Votre état a besoin de temps pour muter, et puisque console.log(this.state.boardAddModalShow)
s'exécute avant que l'état mute, vous obtenez la valeur précédente en sortie. Donc, vous devez écrire la console dans le rappel de la fonction setState
openAddBoardModal(){
this.setState({ boardAddModalShow: true }, function () {
console.log(this.state.boardAddModalShow);
});
}
setState
est asynchrone. Cela signifie que vous ne pouvez pas appeler setState sur une ligne et que l’état a changé sur la ligne suivante.
selon documentation React
setState()
ne mute pas immédiatementthis.state
mais crée une transition d'état en attente. Accéder àthis.state
après avoir appelé cette méthode peut potentiellement renvoyer la valeur existante. Il n'y a aucune garantie de fonctionnement synchrone des appels à setState et les appels peuvent être mis en lot pour des gains de performances.
Pourquoi rendraient-ils async de setState
En effet, setState modifie l'état et provoque la restitution. Cela peut être une opération coûteuse et le rendre synchrone risque de ne pas répondre au navigateur.
Ainsi, les appels setState sont asynchrones ainsi que mis en lots pour une meilleure expérience et performance de l'interface utilisateur.
heureusement setState prend un rappel. Et c'est là que nous obtenons l'état mis à jour. Considérez cet exemple.
this.setState(
{ name: "Mustkeom" },
() => { //callback
console.log(this.state.name) // Mustkeom
}
);
Donc, lorsque le rappel est déclenché, this.state est l'état mis à jour. Vous pouvez obtenir des données mutées/mises à jour dans un rappel.
Comme setSatate est une fonction asynchrone, vous devez donc consolider l'état en tant que rappel.
openAddBoardModal(){
this.setState({ boardAddModalShow: true }, () => {
console.log(this.state.boardAddModalShow)
});
}
setState()
ne met pas toujours le composant à jour immédiatement. Il peut regrouper ou différer la mise à jour à plus tard. Cela rend la lecture de this.state juste après l'appel de setState()
un piège potentiel. À la place, utilisez componentDidUpdate
ou un rappel setState
(setState(updater, callback)
), dont l'un ou l'autre est garanti pour se déclencher après l'application de la mise à jour. Si vous devez définir l'état en fonction de l'état précédent, consultez l'argument ci-dessous pour le programme de mise à jour.
setState()
conduira toujours à un rendu à moins que shouldComponentUpdate()
ne retourne pas false. Si des objets modifiables sont utilisés et que la logique de rendu conditionnel ne peut pas être implémentée dans shouldComponentUpdate()
, l'appel de setState()
uniquement lorsque le nouvel état diffère de l'état précédent évite les rediffusions inutiles.
Le premier argument est une fonction de mise à jour avec la signature:
(state, props) => stateChange
state
est une référence à l'état du composant au moment où le changement est appliqué. Il ne devrait pas être directement muté. Au lieu de cela, les modifications doivent être représentées en construisant un nouvel objet basé sur les entrées d'état et d'accessoires. Par exemple, supposons que nous voulions incrémenter une valeur dans l'état de props.step:
this.setState((state, props) => {
return {counter: state.counter + props.step};
});
Oui car setState est une fonction asynchrone. Le meilleur moyen de définir l'état juste après l'écriture de cet état consiste à utiliser Object.assign comme suit: par exemple, si vous souhaitez définir une propriété isValid sur true, procédez comme suit
Object.assign (this.state, {isValid: true})
Vous pouvez accéder à l'état mis à jour juste après l'écriture de cette ligne.
Si vous voulez suivre l’état de la mise à jour ou non, l’autre façon de faire la même chose est de
_stateUpdated(){
console.log(this.state. boardAddModalShow);
}
openAddBoardModal(){
this.setState(
{boardAddModalShow: true},
this._stateUpdated.bind(this)
);
}
De cette façon, vous pouvez appeler la méthode "_stateUpdated" chaque fois que vous essayez de mettre à jour l'état pour le débogage.
setState est une fonction asynchrone, vous devrez donc peut-être l'utiliser comme,
this.setState({key:value},()=>{ callYourFunction(this.state.key) });
setState()
est asynchrone. Le meilleur moyen de vérifier si l'état est en cours de mise à jour serait dans la componentDidUpdate()
et de ne pas mettre un console.log(this.state.boardAddModalShow)
après this.setState({ boardAddModalShow: true })
.
selon React Docs
Pensez à setState () comme une requête plutôt que comme une commande immédiate pour mettre à jour le composant. Pour une meilleure performance perçue, React peut la retarder, puis mettre à jour plusieurs composants en un seul passage. React ne garantit pas que les changements d'état sont appliqués immédiatement
Selon React Docs
React ne garantit pas que les changements d'état sont appliqués immédiatement. Cela rend la lecture de this.state juste après l'appel de setState () un potentiel
pitfall
et peut éventuellement renvoyer la valeurexisting
en raison deasync
nature. Utilisez plutôtcomponentDidUpdate
ou un rappelsetState
exécuté juste après la réussite de l'opération setState. En règle générale, nous vous recommandons d'utilisercomponentDidUpdate()
pour une telle logique.
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class App extends React.Component {
constructor() {
super();
this.state = {
counter: 1
};
}
componentDidUpdate() {
console.log("componentDidUpdate fired");
console.log("STATE", this.state);
}
updateState = () => {
this.setState(
(state, props) => {
return { counter: state.counter + 1 };
});
};
render() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<button onClick={this.updateState}>Update State</button>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
this.setState({
isMonthFee: !this.state.isMonthFee,
}, () => {
console.log(this.state.isMonthFee);
})