Home > Net >  Adding item in array in an object with usestate replaces it instead
Adding item in array in an object with usestate replaces it instead

Time:03-24

Looked everywhere but can't find a solution to my problem. I have a listener for when messages are being added which works but for some reason when a message gets added the array in the usestate the messages array gets replaced so there's one ever one item in there, when I add the onmModified in to it, it gets even worse... Instead of updating that value it empties the entire array...

  const { chatID } = route.params;

  const [values, setValues] = useState<States>({
    chat: chats[chats.findIndex((c) => c.chatID === chatID)],
    messages: [],
    isLoading: false,
    input: "",
    isSending: false,
  });

  useEffect(() => {
    initMessages(); // Fetches previous messages which works but the listener below finds a need to replace the array instead of just adding to it... 
    
    const unsubMessages = MessagesAPI.incomming(values.chat,
      (message) => {
        console.log("onAdded: "   message?.messageID);
        setValues({ ...values, messages: [...values.messages, message!] }); // This...
      }, (message) => {
        console.log("onModified: "   message?.messageID);
        setValues({
          ...values, messages: values.messages.map((m: Message, idx: number) => {
            if (m.messageID === message!.messageID) {
              return message!;
            }
            return m;
          })
        }); // And this......
      }, (message) => {
        console.log("onRemoved: "   message?.messageID);
      }, (err) => {
        console.log(err);
      }, () => {
        console.log("Closed...");
      });
  }, []);

CodePudding user response:

You are running this inside of a useEffect hook. Whenever an effect uses something that may change from one render cycle to the next (like state and props variables), it needs to be added to the dependency array. Otherwise your effect will "retain" stale variables. Be extra careful about this, especially when your effect is running just once, like yours (because of the empty [] dependency array).

When you listener is running, it's probably seeing a stale value of the variable values. As it was when you set up the listener on the useEffect.

So, in theory, you would need to add the values variable to your dependency array. And setup and remove the listener everytime that the values variable changes.

But from seeing what you are trying to do, it's easier to just not use the values variable at all, and just use the functional form of the setState call.

You can access the prevState variable, which will always be up-to-date with the previous state that you are using to update it to the new state.

Replace this:

setValues({ ...values, messages: [...values.messages, message!] });

With this:

setValues((prevState) => 
  ({ ...prevState, messages: [...prevState.messages, message!] })
);

Do the same for the other setValues call.

See if that works.

  • Related