Djaenike
Djaenike

Reputation: 1865

Updating React child component after state change

I made a text input box which, when submitted, will update the state of the messages in the parent component. The messages in the parent component are passed down to the message display. I'd like the component responsible for displaying the messages to update and display the messages after each submission, but can't figure out how to do it. I made a code sandbox here:

https://codesandbox.io/s/unruffled-pasteur-nz32o

Here's my code:

Parent component:

import React, { Component } from "react";
import Messages from "./Messages";
import Input from "./Input";

export default class Container extends Component {
  constructor(props) {
    super(props);
    this.state = {
      messages: []
    };
  }

  updateMessage(message) {
    this.state.messages.push(message);
  }

  render() {
    return (
      <div>
        <Messages messages={this.state.messages} />
        <Input updateMessage={message => this.updateMessage(message)} />
      </div>
    );
  }
}

Message input component:

import React, { Component } from "react";

export default class Input extends Component {
  constructor(props) {
    super(props);
    this.state = {
      message: ""
    };
 }

  sendMessage() {
    this.props.updateMessage(this.state.message);
    this.setState({ message: "" });
  }

  render() {
    return (
      <div>
        <input
          type="text"
          value={this.state.message}
          onChange={({ target }) => {
            this.setState({ message: target.value });
          }}
        />
        <button onClick={() => this.sendMessage()}>Send</button>
      </div>
    );
  }
}

Message display component:

import React, { Component } from "react";

export default class Messages extends Component {
  render() {
    return this.props.messages.map(message => {
      return <div>{message}</div>;
    });
  }
}

Thanks!

Upvotes: 1

Views: 1302

Answers (3)

Dostonbek Oripjonov
Dostonbek Oripjonov

Reputation: 1674

Your error is in this part

updateMessage(message) {
    this.state.messages.push(message);
  }

You can not change state directly. You must use setState() method to change state

updateMessage(message) {
        this.setState({
             messages : [...this.state.messages, message]
        });
      }

Upvotes: 1

Michael Yaworski
Michael Yaworski

Reputation: 13483

From your code:

updateMessage(message) {
  this.state.messages.push(message);
}

You're modifying the state directly and you're not supposed to do that (except for in the constructor). It won't cause a re-render in this way. Instead, clone the state, modify it, then update the state via setState. Calling setState will invoke a re-render.

updateMessage(message) {
  this.setState({
    messages: [...this.state.messages, message],
  });
}

Upvotes: 3

Ishan Joshi
Ishan Joshi

Reputation: 525

In your updateMessage(message) method, can you try:

updateMessage(message) {
    let { messages } = this.state;
    messages.push(message)
    this.setState({ messages })
}

Upvotes: 3

Related Questions