Search code examples
javascriptangularobservableimmutabilityngrx

Angular ngrx: assign a readonly property


I'm building an Angular App with Ngrx and I'm encountering a problem. Here it is:

In the OnInit, i launch dispatch and selector for getting my datas from store and i want to edit these datas.
I get an error 'Cannot assign to read only property 'title' of object '[object Object]'' when i try to do that: x.title = ${x.title} (${count})

I understand why i can't reassign, state is immutable. Yes but, how can i edit my datas? I started by do that in the effect but it's display logic, i think i've to do that in a component logic.

There's my OnInit function:

ngOnInit() {
    this.store.dispatch(new GetAllProducts());
    this.store.select(selectResourcesList).pipe(
        distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b))
    )
        .pipe(tap((res => {
            res.resources.map(x => {
                let count = 0;
                res.events.map(y => {
                    if (y.resourceId === x.id) {
                        count += y.extendedProps.quantity;
                        return count;
                    }
                    return count;
                });
                x.title = `${x.title} (${count})`;
            });
        })))
        .subscribe((res) => {
            this.resources = res.resources;
            this.events = res.events;
            this.cdr.detectChanges();
        });

}

edit: I had try to edit my data in the subscribe like this, but get the same error:

    ngOnInit() {
    this.store.dispatch(new GetAllProducts());
    this.store.select(selectResourcesList).pipe(
        distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)))
        .subscribe((res) => {
            const tempResources = [...res.resources];
            const tempEvents = [...res.events];
            tempResources.map(x => {
                let count = 0;
                tempEvents.map(y => {
                    if (y.resourceId === x.id) {
                        count += y.extendedProps.quantity;
                    }
                });
                x.title = `${x.title} (${count})`;
            });
            this.resources = tempResources;
            this.events = tempEvents;
            this.cdr.detectChanges();
        });
}

Thanks in advance for your help ;-)


Solution

  • I found a solution for bypass store immutability:

    I had to create a copy of result of selector (with spread operator) and do the changes on it.

    Like this:

        ngOnInit() {
        this.store.dispatch(new GetAllProducts());
        this.store.select(selectResourcesList).pipe(
            distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)))
            .subscribe((res) => {
                let tempResources = [...res.resources];
                let tempEvents = [...res.events];
                tempResources = tempResources.map(x => {
                    let count = 0;
                    tempEvents = tempEvents.map(y => {
                        if (y.resourceId === x.id) {
                            count += y.extendedProps.quantity;
                        }
                        return y;
                    });
                    x = {
                        ...x,
                        title: `${x.title} (${count})`
                    };
                    return x;
                });
                this.resources = tempResources;
                this.events = tempEvents;
                this.cdr.detectChanges();
            });
    }