Обновить элемент в массиве объектов, имеющих определенные критерии

#javascript #redux #react-redux #immutability

#javascript #redux #реагировать-redux #неизменность

Вопрос:

У меня есть массив комнат чатов, в каждой комнате есть свойство массива сообщений.

 // 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"
  },
  

Мой редуктор определен, как показано ниже, и он получает данные типа String (roomName), с помощью которых я выбираю комнату, для свойств просмотра сообщений которой должно быть установлено значение true.

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

Я уже давно борюсь с этим. Любая помощь будет высоко оценена.

Редактировать: то, что я пытаюсь сделать, это установить свойство ‘seen’ для каждого сообщения комнаты (индекс которого возвращается roomIndex) в значение true.

Комментарии:

1. можете ли вы подробнее рассказать, чего именно вы хотите достичь здесь?

2. @MAS, извините, это было недостаточно ясно, я добавил небольшое объяснение того, что я пытаюсь сделать.

Ответ №1:

Что-то вроде этого должно сработать

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

НО. Вам следует лучше нормализовать структуру redux и использовать immer, чтобы избежать вложенных обновлений.

Комментарии:

1. Это сделало свое дело, спасибо за ответ, а также за предложение. с благодарностью, @Tarabanko