Search code examples
angulartypescriptrxjsngrx

How Can I update the value of property of an observable in reducer?


I want to update the state of all mydirect message with specific user when i start an event, how can i update this property with filtering only this user and the messages which are not seen yet...thanks

 //----------State Message---------------//
   //----------State Message---------------//
 on(directMessagesAction.seenMyRecievedMessage, (state, { payload }) => {
    const messages = [...state.allDirectMessages];
    for (let m of messages) {
      if (
        m.messageModel.from.userName == payload.userName &&
        m.messageModel.isSeen == false
      ) {
        m.messageModel.isSeen = true;
      }
    }

    return { ...state, allDirectMessages: messages };
  }),


this is the model of directMessage

import { MessageViewModel } from "./messageViewModel";
import { OnlineUserModel } from "./onlineUserModel";
export class DirectMessage {
  public fromOnlineUser: OnlineUserModel | null = {
    userName: "",
    email: "",
    firstname: "",
    profilePic: "",
    isProfileComplete: "",
    isActive: "",
  };
  public messages = "";

  public messageModel: MessageViewModel = {
    content: "",
    timestamp: "",
    from: null,
    to: null,
    avatar: "",
    attachement: "",
    fileSize: "",
    fileNameSaved: "",
    isSeen: false,
    isSeenDate: "",
  };
  ////-------- ***** try with message Oject *****------/////
}


Solution

  • The problem is you can't change the state you get passed by the method. It is read-only. As a result your changes to state.allDirectMessages cause the error.

    Cannot assign to read only property 'messageModel' of object '[object Object]' ... allDirectMessage array of DirectMessage

    The easiest solution is to make a copy of the part you want to change and then override it afterwards.

    on(directMessagesAction.seenMyRecievedMessage, (state, { payload }) => {
        const messages = [...state.allDirectMessages]
        for (let m of messages) {
            if (m.messageModel.from.userName == payload.userName && m.messageModel.isSeen == false) {
                m.messageModel.isSeen = true;
            }
        }
    
        return { ...state, allDirectMessages: messages };
      }),
    

    EDIT:
    my replication of the logic

    const messages: Message[] = [
        { sender: 'Me', isSeen: false },
        { sender: 'You', isSeen: false }
    ]
    
    // map solution
    const updated = messages.map(m => ({ ...m, isSeen: true } as Message))
    console.log(updated);
    
    // loop solution
    for (let m of messages) {
        m.isSeen = true;
    }
    console.log(messages);