web-dev-qa-db-fra.com

setState ne met pas à jour l'état immédiatement

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
67
Sydney Loteria

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);
}
7
Spock

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édiatement this.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.

116
Shubham Khatri

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.

21
Asif J

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)
    });
}
11
Adnan shah

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};
});
5
Aman Seth

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.

2
Dipanshu Sharma

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.

2
Ravin Gupta

setState est une fonction asynchrone, vous devrez donc peut-être l'utiliser comme,

this.setState({key:value},()=>{ callYourFunction(this.state.key) });
0
Preetham NT

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

0
stuli

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 valeur existing en raison de async nature. Utilisez plutôt componentDidUpdate ou un rappel setState exécuté juste après la réussite de l'opération setState. En règle générale, nous vous recommandons d'utiliser componentDidUpdate() pour une telle logique.

Exemple:

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);

0
khizer
 this.setState({
    isMonthFee: !this.state.isMonthFee,
  }, () => {
    console.log(this.state.isMonthFee);
  })