coredumped0x
coredumped0x

Reputation: 848

Update element in array of objects that have certain criteria

I have a an array of chat rooms, each room has a messages array property.

// state
const INITIAL_STATE = {
        myRooms: {
            rooms: [],
            isLoading: false,
            isLoaded: false,
            isError: false,
        },
};

A room and its elements is defined as

{
"creator": {
  "username": "LangCodex"
},
"joiner": {
  "username": "Bingo"
},
"date_created": "2020-10-04T19:23:01.380918",
"messages": [],
"name": "9496dd0a223f712f4a9d2f3fba4a0ab0",
"status": "offline"

}

A message and its elements is defined as below:

  {
    "author": {
      "username": "Bingo"
    },
    "recipient": {
      "username": "LangCodex"
    },
    "body": "hello",
    "date": "2020-10-07T11:11:25.828269",
    "id": 602,
    "room": "9496dd0a223f712f4a9d2f3fba4a0ab0",
    "seen": false,
    "type": "text"
  },

My reducer is defined as below and it's receiving data of type String (roomName) by which I select the room whose messages's seen properties are to be set to true.

case 'MARK_CHAT_AS_READ': {
    const roomIndex = state.myRooms.rooms.findIndex(r => r.name === action.payload.roomName);
   // magic happens here
   return {...state}
}

I have been struggling with this one for quite a while now. Any help would be much appreciated.

Edit: What I am trying to do is to set the 'seen' property of every message of the room (whose index is returned by roomIndex) to true.

Upvotes: 1

Views: 63

Answers (1)

Yury Tarabanko
Yury Tarabanko

Reputation: 45121

Something like this should do the trick

case 'MARK_CHAT_AS_READ': {
   return {
     ...state, // copy state
     myRooms: {
       ...state.myRooms, // copy myRooms
       rooms: state.myRooms.rooms.map(room => { // create new rooms array

         // keep room untouched if the name is different
         if (room.name !== action.payload.roomName) return room;

         return { // create new room
           ...room,
           // with new messages array, containing updated values
           messages: room.messages.map(message => ({...message, seen: true}))
         };
       }),
     }
   }
}

BUT. You should better normalize redux structure and use immer to avoid nested updates.

Upvotes: 3

Related Questions