web-dev-qa-db-fra.com

Impossible de définir l'état dans ComponentWillMount

Je crée une application de chat simple dans laquelle je fais un appel api de ma base de données via axios, qui renvoie un tableau d'objets de message. Je peux obtenir les données lorsque je passe un appel axios dans ComponentWillMount. Ensuite, j'essaie de définir l'état pour afficher la conversation. Voici le code:

export default class Chat extends Component {
  constructor(props){
    super(props);

    this.state = {
      messages : [],
      message : '',
    };
    this.socket = io('/api/');
    this.onSubmitMessage = this.onSubmitMessage.bind(this);
    this.onInputChange = this.onInputChange.bind(this);
  }

  componentWillMount() {
    axios.get(`api/messages`)
      .then((result) => {
        const messages = result.data
        console.log("COMPONENT WILL Mount messages : ", messages);
        this.setState({ 
          messages: [ ...messages.content ] 
        })
  })
};

J'ai lu des articles sur les fonctions du cycle de vie et l'état des paramètres, et il semble que je fasse ce qu'il faut. 

Encore une fois, les appels axios fonctionnent bien, le réglage de l’état ne fonctionne pas. Je vois encore un tableau vide. Merci d'avance!

EDIT: Voici la solution à mon problème en particulier. C'était enterré dans un commentaire, alors j'ai pensé le laisser ici ..

"J'ai découvert le problème. C'était en fait dans la façon dont j'avais analysé mes données. L'opérateur de diffusion sur ... messages.content n'a pas fonctionné car messages.content n'existe pas. Messages [i] .content existe. Donc mon correctif était de ne diffuser que ... des messages Puis, dans un composant enfant, je mappe sur les objets et analyse la propriété .content. Merci pour l'aide les gars! "

10
Phil

Dans votre cas, votre setState() ne fonctionnera pas car vous utilisez setState() dans un rappel asynchrone

Working Fiddle: https://jsfiddle.net/xytma20g/3/

Vous effectuez un appel API qui est asynchrone. Ainsi, la setState ne sera invoquée qu’après la réception des données. Il ne fait rien avec componentWillMount ou componentDidMount. Vous devez gérer la message vide dans votre rendu. Lorsque vous recevez vos données de l'API, définissez ces données sur l'état et le composant sera rendu de nouveau avec le nouvel état qui sera reflété dans votre rendu. 

Pseudo code:

export default class Chat extends Component {
  constructor(props){
    super(props);

    this.state = {
      messages : [],
      message : '',
    };
    this.socket = io('/api/');
    this.onSubmitMessage = this.onSubmitMessage.bind(this);
    this.onInputChange = this.onInputChange.bind(this);
  }

  componentWillMount() {
    axios.get(`api/messages`)
      .then((result) => {
        const messages = result.data
        console.log("COMPONENT WILL Mount messages : ", messages);
        this.setState({ 
          messages: [ ...messages.content ] 
        })
  })

  render(){
    if(this.state.messages.length === 0){
     return false //return false or a <Loader/> when you don't have anything in your message[]
    }

   //rest of your render.
  }
}; 
11
Pranesh Ravi

composantWillMount () est appelé immédiatement avant le montage. Il est appelé avant render (), donc la définition de l’état dans cette méthode sera pas déclencher un re-rendu. Évitez d’introduire des effets secondaires ou abonnements dans cette méthode. docs

Donc, vous devez appeler componentDidMount comme-

componentDidMount() {
    axios.get(`api/messages`)
      .then((result) => {
        const messages = result.data
        console.log("COMPONENT WILL Mount messages : ", messages);
        this.setState({ 
          messages: [ ...messages.content ] 
        })
  })
0
Fazal Rasel