更新具有特定条件的对象数组中的元素

Update element in array of objects that have certain criteria

我有一个聊天室数组,每个房间都有一个消息数组属性。

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

房间及其元素定义为

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

}

消息及其元素定义如下:

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

我的 reducer 定义如下,它正在接收 String (roomName) 类型的数据,据此我 select 房间的消息可见属性将被设置为 true。

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

我已经为这个问题苦苦挣扎了一段时间。任何帮助将不胜感激。

编辑: 我想要做的是将房间(其索引由 roomIndex 返回)的每条消息的 'seen' 属性 设置为 true。

像这样应该可以解决问题

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

但是。你最好 normalize redux structure and use immer 避免嵌套更新。