2

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));
}

3 Answers 3

3

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;
    }),
  });
};
Sign up to request clarification or add additional context in comments.

Comments

1

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.

2 Comments

this is an example, i have tried to push the message in different ways, but nothing has worked, it makes the notification null
@sairam I edited my answer to give you an example that works
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.