Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update nested state structure in Angular / ngrx reducer

I have a nested state structure that represents a time entry table. I store an array of TimeEntryRow objects, where each row object has it's own array of TimeEntry objects. Note that the objects store an index that represents their position in the table.

export interface TimeState {
    timeEntryRows?: TimeEntryRow[];
    ...
}

export class TimeEntryRow {
    rowIndex: number;
    timeEntries: TimeEntry[];
    ...
}

export class TimeEntry {
    cellIndex: number;
    hours: number;
    ...
}

I have a reducer that is attempting to update the hours of a single cell in the table, but I'm having some issues getting it to work. With the following action case, the state remains unchanged:

case timeEntryActions.HOURS_CHANGED_ACTION: {
    return {
        ...state,
        timeEntryRows: {
            ...state.timeEntryRows.map(row => {
                return row.rowIndex !== action.payload.rowIndex ? row : {
                    ...row,
                    timeEntries: {
                        ...row.timeEntries.map(te => {
                            return te.cellIndex !== action.payload.cellIndex ? te : {
                                ...te,
                                hours: action.payload.hours
                            }
                        })
                    }
                }
            })
        }
    }
}

Any help would be greatly appreciated.

like image 735
ElliotSchmelliot Avatar asked Oct 29 '22 15:10

ElliotSchmelliot


1 Answers

Looks like I was accidentally setting my array properties timeEntryRows and timeEntries to objects, rather than arrays.

One more reason to avoid nested state as much as possible, as the reducers get longer and more complicated. Ended up using this Redux resource on how to properly update nested objects.

New code:

case timeEntryActions.HOURS_CHANGED_ACTION: {
    return {
        ...state,
        timeEntryRows: state.timeEntryRows.map(row => {
            return row.rowIndex !== action.payload.rowIndex ? row : {
                ...row,
                timeEntries: row.timeEntries.map(te => {
                    return te.cellIndex !== action.payload.cellIndex ? te : {
                        ...te,
                        hours: action.payload.hours
                    }
                })
            }
        })
    }
}
like image 190
ElliotSchmelliot Avatar answered Nov 10 '22 05:11

ElliotSchmelliot