Reputation: 848
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
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