Add element to a state React
I already have a state with this:
this.setState({
conversation:
(
<div>
{conversation.map(element => {
if (element.id === this.props.id) {
return(
<div className="row msg_container base_sent">
<div className="col-md-10 col-xs-10">
<div className="messages msg_sent">
<p>{element.message}</p>
</div>
</div>
</div>
)
}
else {
return(
<div className="row msg_container base_receive">
<div className="col-md-10 col-xs-10">
<div className="messages msg_receive">
<p>{element.message}</p>
</div>
</div>
</div>
)
}
})}
</div>
)
})
Now I would like to update it with new information. So add another div to it.
Something like that:
this.setState({conversation: previousConversation + new div})
How can I do it? Or I need to set a new state from zero
Solution 1:
As per React docs (webarchive source):
What Should Go in State?
State should contain data that a component's event handlers may change to trigger a UI update. In real apps this data tends to be very small and JSON-serializable. When building a stateful component, think about the minimal possible representation of its state, and only store those properties in
this.state
. Inside ofrender()
simply compute any other information you need based on this state. You'll find that thinking about and writing applications in this way tends to lead to the most correct application, since adding redundant or computed values to state means that you need to explicitly keep them in sync rather than rely on React computing them for you.What Shouldn’t Go in State?
this.state
should only contain the minimal amount of data needed to represent your UI's state. As such, it should not contain:
- Computed data: Don't worry about precomputing values based on state — it's easier to ensure that your UI is consistent if you do all computation within
render()
. For example, if you have an array of list items in state and you want to render the count as a string, simply renderthis.state.listItems.length + ' list items'
in yourrender()
method rather than storing it on state.- React components: Build them in
render()
based on underlying props and state.- Duplicated data from props: Try to use props as the source of truth where possible. One valid use to store props in state is to be able to know its previous values, because props can change over time.
In your case, move your html into your render function. Then store a condition or data in your state that would be used to trigger the addition of another div to your html either by conditionally rendering some html or by adding another div to an array inside a .map function based on adding more data to your state.
Example:
Class Example render React.Component{
state = {
comments: [
{ message:"comment 1", id: 1, timeStamp: "" },
{ message:"comment 2", id: 2, timeStamp: "" },
{ message:"comment 3", id: 3, timeStamp: "" }
]
}
componentDidMount = () => {
//update data from api...
.then(data => this.setState({ comments: data }))
}
render(){
conversation.map(element => {
if (element.id === this.props.id) {
return(
<div className="row msg_container base_sent">
<div className="col-md-10 col-xs-10">
<div className="messages msg_sent">
<p>{element.message}</p>
</div>
</div>
</div>
)
}
else {
return(
<div className="row msg_container base_receive">
<div className="col-md-10 col-xs-10">
<div className="messages msg_receive">
<p>{element.message}</p>
</div>
</div>
</div>
)
}
})
}
}
Solution 2:
I don't think it's a good idea to store jsx components in the state of a component. I think you should only save the data in the state needed to render the component.
If you really want to store jsx in the state, why won't you define your 'conversation' property as array? Then you'll be able to add new components to it.
this.setState({
conversation: [
(<div>first</div)
]
});
const currentConversation = state.conversation;
currentConversation.push((<div>new div</div>));
this.setState({conversation: currentConversation})
But better to only store the data ie 'first' and 'new div'