简体   繁体   中英

React child props doesn't update when parent state change

So here's the main problem : I open a websocket where I need to read a sessionId in the first coming message to use it for further messages sent. This needs therefore to be done only once.

I have a child component "processMessage" that looks like this :

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import ChatBot from 'react-simple-chatbot';

export class ProcessMessage extends Component {
  constructor(props) {
     super(props);

     this.state = {
       messages: [],
     };
   }

  componentWillMount() {
    const input = {
      type: 'user',
      sessionId: this.props.sessionId,
      msg: this.props.inputMessage,
    };
    //send message to websocket
    this.props.connection.send(input)

    this.props.connection.onmessage = evt => {
      // add the new message to state
      const msg = JSON.parse(evt.data);

      let responseText = msg.msg;
      this.setState({
        messages : responseText
      })
    };



  }


  render() {
    return <div>{ this.state.messages}</div>;
  }
}

and an "app" parent that open the websocket and get the sessionId component that looks like this (didnt post everything):

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { ProcessMessage } from './components/processMessage.js';

export class App extends React.Component {
  constructor(props) {
    super(props);
    // Assign state itself, and a default value for items


  }
    componentWillMount() {
        const url = 'ws://localhost:4040';

        // this open websocket service
        this.connection = new WebSocket(url);

        this.setState(
          { connection:this.connection }
        );
        var sessionId;
        // listen to onmessage event
        this.connection.onmessage = evt => {

        // add the new message to state
          const msg = JSON.parse(evt.data);
            if (msg.type = "sessionId") {
              sessionId=msg.msg;
              console.log("now received sessionId " +sessionId);
              this.setState(
                { sessionId: sessionId}
              );

            }
        };
  }

  render(){
  return <ProcessMessage sessionId={this.state.sessionId} connection={this.state.connection} inputMessage={this.state.inputMessage}/>
  }

So what's working is that the message is correctly sent with the connection props (socket open) but the sessionId is undefined in the child component because it takes some times to receive the first response of the socket where I get the sessionId but the component doesn't seems to re-render with the new props.

I also try to put in the child component processMessage :

componentWillReceiveProps(nextProps) {
  this.setState({ sessionId: nextProps.sessionId});  
}

with no success. Am I missing something obvious ?

You should use componentDidMount lifecycle function as setting state in componentWillMount doesn't trigger a rerender and hence the props don't update

From the React docs:

componentWillMount()

componentWillMount() is invoked immediately before mounting occurs. It is called before render(), therefore setting state synchronously in this method will not trigger a re-rendering . Avoid introducing any side-effects or subscriptions in this method.

This is the only lifecycle hook called on server rendering. Generally, we recommend using the constructor() instead.

componentDidMount() {
        const url = 'ws://localhost:4040';

        // this open websocket service
        this.connection = new WebSocket(url);

        this.setState(
          { connection:this.connection }
        );
        var sessionId;
        // listen to onmessage event
        this.connection.onmessage = evt => {

        // add the new message to state
          const msg = JSON.parse(evt.data);
            if (msg.type = "sessionId") {
              sessionId=msg.msg;
              console.log("now received sessionId " +sessionId);
              this.setState(
                { sessionId: sessionId}
              );

            }
        };
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM