Reputation: 35
this is my state
this.state = {
notification: [{
from: {
id: someid,
name: somename
},
message: [somemessage]
},
{..},
{..},
]
}
Now if i get a new message from someid, i have to push that new message into message array of someid
I tried to push that message in different ways, but nothing has worked
I tried it in this way, but im not able to push a new message into message array
if (this.state.notification) {
for (let q = 0; q < this.state.notification.length; q++) {
if (
this.state.notification[q] &&
this.state.notification[q].from &&
this.state.notification[q].from.id === r.from.id
) {
this.setState({
notification: [
...this.state.notification[q].messages,
this.state.notification[q].messages.push(r.message),
],
});
return console.log(this.state.notification[q].messages)
}
}
} else {
this.setState({
notification: [{
from: r.from,
messages: [r.message]
}, ]
});
return console.log(JSON.stringify(this.state.notification));
}
Upvotes: 2
Views: 75
Reputation: 4987
I'm pretty sure you can't do this: this.state.notification[q].messages.push(r.message)
. You can't mutate your state directly. You should work with a copy o your state, modify it with your code that seems to be ok, and then do the setState(...)
.
Here is a repro on Stackblitz that works. Here is the code :
import React, { Component } from "react";
import { render } from "react-dom";
import "./style.css";
class App extends Component {
constructor() {
super();
this.state = {
notifications: [
{
from: { id: 0, name: "Quentin" },
message: ["Message 1"]
},
{
from: { id: 1, name: "John" },
message: ["Message 1"]
},
{
from: { id: 2, name: "Henry" },
message: ["Message 1"]
}
]
};
this.pushMessage = this.pushMessage.bind(this);
}
pushMessage (id, message) {
const newState = Object.assign([], this.state);
newState.notifications.forEach(notif => {
if (notif.from.id === id) {
notif.message.push(message);
}
});
this.setState(newState, () => console.log(this.state));
};
render() {
return (
<div>
<button onClick={() => this.pushMessage(1, "Hello World")}>
Push message
</button>
</div>
);
}
}
render(<App />, document.getElementById("root"));
I only handle the push of a message in an existing notification, you already got the other case.
Upvotes: 1
Reputation: 845
The first argument to setState
is an updater function that takes the previous state as an argument. I think you should use this fact to update your state correctly.
Check out this answer https://medium.com/@baphemot/understanding-reactjs-setstate-a4640451865b.
Upvotes: 0
Reputation: 293
First of all, I think structuring your state as a 2d array is not a good idea. But you can try this
const pushMessage = (someId, someMessage) => {
this.setState({
notifications: this.state.notifications.map((notification) => {
if (notification.from.id === someId) {
return {
...notification,
messages: [...notification.messages, someMessage],
};
}
return notification;
}),
});
};
Upvotes: 3