Reputation: 1865
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
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
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
Reputation: 525
In your updateMessage(message)
method, can you try:
updateMessage(message) {
let { messages } = this.state;
messages.push(message)
this.setState({ messages })
}
Upvotes: 3