Using angular-redux, how do I select a slice of state from an element that exists in an array?

Viewed 273

I am using angular-redux to create a store. The store has a slice called 'roomListState' which is an array of rooms. I have a container component that subscribes to this list and creates a view of each of the rooms in the list that have their open property set to true.

When there is an update to the messages in a room, I update the store with the reducer function shown below. The container component subscribes to updates of the room list. It filters the list (with the rs.open property), into its list of open rooms. Whenever any room is changed, the container component list of open rooms is updated causing all open rooms to be redrawn.

Is there a better way to display open rooms without having to redraw all of them? As a side effect of the recreating all of the rooms, the room that the user sent the message from is losing focus.

export interface IAppState {
  userState: IUserState;
  roomListState: IRoomListState;
}
export interface IRoomListState {
  rooms: Array<Room>;
}
//...
// adds an array of messages to a room using a supplied id
function addMessagesToRoom(state: IRoomListState, action: IRoomListAction): IRoomListState {
  let newState = { ...state };
  let newRooms = [...state.rooms];
  newState.rooms = newRooms;
  let roomIndex = newRooms.findIndex((r: Room) => r.id === action.roomId);
  if (roomIndex === -1) {
    console.log('Error: room id not found for message update. State not updated');
    return state;
  } else {
    newRooms[roomIndex] = new Room(state.rooms[roomIndex]);
    let newMessages = [...newRooms[roomIndex].messages, ...action.messages];
    newRooms[roomIndex].messages = newMessages;
    return newState;
  }
}

My container component is subscribing to updates of the roomList slice of the state:

public ngOnInit() {
  this.openRooms$ = this.ngRedux.select(['roomListState', 'rooms']).map((rs: Array<Room>) => {
    let ors: Array<Room> = [];
    rs.forEach((r: Room) => {
      if (r.open) {
        ors.push(r);
      }
    });
    return ors;
  });
  this.openRooms$.subscribe((rs: Array<Room>) => {
    this.openRooms = rs;
    // console.log('Open Rooms List is now: ', this.openRooms);
  })
0 Answers
Related