Modifying the nested state structure within an Angular / ngrx reducer

In my application, I have a complex state structure that represents a time entry table. Each table row is stored as an array of TimeEntryRow objects, where each row object contains its own array of TimeEntry objects. It's important to note that each object maintains an index representing its position in the table.

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

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

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

I'm currently facing challenges with updating the hours for a single cell in the table using a reducer. Despite implementing the following action case, the state doesn't seem to change:

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

If anyone has insights or suggestions on how to resolve this issue, I would greatly appreciate it.

Answer №1

It appears that I unintentionally assigned objects instead of arrays to my array properties timeEntryRows and timeEntries.

This serves as another reminder to minimize the use of nested state, as it can lead to more complex reducers. I found a helpful resource on updating nested objects in Redux which guided me in resolving this issue.

Here is the updated code snippet:

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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Mapping type property names in Typescript for substitution

I am working on a function that accepts two objects as parameters: one representing a model and the other representing a mapping. The function then returns an object with two properties: one showing the base model and the other displaying the model with ea ...

Using Conditionals in React Props

In the process of developing a component that requires two props, inside and position, I've encountered an interesting dilemma. When inside is set to true, then position is limited to left or bottom. However, if inside is set to false, then position c ...

What is the importance of having typings when using TypeScript?

I recently came across a post on setting up Material-UI for React with Typescript on Stack Overflow: How to setup Material-UI for React with Typescript? As someone who is brand new to typescript, I initially assumed that typescript was simply a superset o ...

TypeScript enables the use of optional arguments through method overloading

Within my class, I have defined a method like so: lock(key: string, opts: any, cb?: LMClientLockCallBack): void; When a user calls it with all arguments: lock('foo', null, (err,val) => { }); The typings are correct. However, if they skip ...

What is the best way to initiate multiple processes in Node.js and ensure they finish before proceeding?

When working with Node.js and TypeScript, my goal is to initiate multiple processes using the spawn function. Afterwards, I aim to ensure all of these processes are completed before proceeding to execute any additional commands. ...

Can you send the value of an Angular-generated input to a function even if it doesn't have an ID associated with it?

Is there a way to make the cells in a dynamically generated table editable? The challenge I am facing is that because the table uses MatTableDataSource in Angular with data from an API, the cell elements cannot have unique IDs. How can I ensure that when a ...

Invoking a redux action from one store slice within a different store slice

I am still learning about using redux. One feature I have implemented in my app is the use of async actions with redux thunk. For instance, one of my actions involves loading movies from an API: export const loadMovies = (url) => async (dispatch) => ...

Sample test scenario for a service function that includes an HTTP subscription using Angular's HTTP RxJS

I have a service method that includes an HTTP call and subscribes immediately to the response code in order to execute the rest of the action command based on it. Here is an example of the service method: processData(id): void { const url = `http://l ...

Which rxjs operator functions similarly to concatmap, but delays the firing of the next request until the current one is completed?

Imagine if I need to make multiple api calls with a high risk of encountering race conditions. If I send 3 requests simultaneously to update the same data on the server, some of the information could be lost. In order to prevent this data loss, I want to ...

The TypeORM connection named "default" could not be located during the creation of the connection in a Jest globalSetup environment

I've encountered a similar issue as the one discussed in #5164 and also in this thread. Here is a sample of working test code: // AccountResolver.test.ts describe('Account entity', () => { it('add account', async () => { ...

Utilizing StyleFunctionProps within JavaScript for Chakra UI Enhancements

I need help figuring out how to implement StyleFunctionProps in my Chakra UI theme for my NextJS project. The documentation on Chakra's website provides an example in Typescript, but I am working with Javascript. Can someone guide me on adapting this ...

Strange error message regarding ES6 promises that is difficult to interpret

Snippet getToken(authCode: string): Promise<Token> { return fetch(tokenUrl, { method: "POST" }).then(res => res.json()).then(json => { if (json["error"]) { return Promise.reject(json); } return new Token ...

Exploring the changes in the store while using redux saga

I'm attempting to create a Redux saga that will monitor a specific variable in the state for changes. When this variable does change, I need to trigger another action. Is there a way to achieve this? Here is my desired approach: yield takeLatest(foo ...

Error: An unauthorized attempt was made to modify property settings for certain users, which are designated as read-only

Within my Ionic app, there exists a specific page where users have the ability to modify information related to a particular city. What I aim to achieve is for these modifications to only be visible to other users who are also located within the same "City ...

VS Code is throwing an Error TS7013, while Typescript remains unfazed

In my Typescript/Angular project, I have the following interface: export interface MyInterface { new (helper: MyInterfaceHelpers); } After compiling the project, no errors are shown by the Typescript compiler. However, VSCode highlights it with squiggl ...

JQuery Searchbar Failing to Hide Divs as Intended

I'm currently facing an issue with my <user-panel> elements, which are dynamically created using ng-repeat. Each of these elements contains child divs with the class user-panel-name. I've been attempting to use the text within these name di ...

Differences Between APP_INITIALIZER and platformBrowserDynamic with provide

I've discovered two different approaches for delaying an Angular bootstrap until a Promise or Observable is resolved. One method involves using APP_INITIALIZER: { provide: APP_INITIALIZER, useFactory: (configService: ConfigurationService) => ( ...

I encountered an error message while running the Angular JS code that I had written, and I am unable to find a solution to resolve it

Every time I attempt to run ng serve, the following error message pops up: "The serve command requires to be run in an Angular project, but a project definition could not be found." I've already experimented with various commands like: npm cache clean ...

Transforming ActivatedRoute.queryParams into a Promise

Instead of subscribing to route.queryParams as an Observable, I want it to be a Promise so that I can use async/await for function calls in ngOnInit. However, my attempt at this is not working as expected. The code below does not produce any output: constr ...

Using `await` inside an if block does not change the type of this expression

Within my code, I have an array containing different user names. My goal is to loop through each name, verify if the user exists in the database, and then create the user if necessary. However, my linter keeps flagging a message stating 'await' h ...