TypeError: Cannot add property 1, object is not extensible↵ at Array.push (<anonymous>)

I am trying to add some data to an array but I am getting not extensible error.

Component code:

this._store.select(p => p.collection.workspaceCollectionPages).subscribe((data: CollectionPageDbModel[]) =>{
      if(data){
      return data.map((collectionPageDbModel)=> {

      this.collectionPages.push(collectionPageDbModel) //Getting error on this line while pushing

    });}

enter image description here

I have four objects in my data var, which I am trying to push in collectionPages, but I am getting extensible error while pushing.

enter image description here collectionPage array where i need to add more data

enter image description here This data I need to push

CollectionPageDbModel:

export class CollectionPageDbModel implements IDbModel {
  public id?: number;
  public collection_version_id: number;
  public user_id?: string;
  public name: string;
  public position?: number = 0;
  public contents: string;
  public created_at?: string;
  public updated_at?: string;
  public server_id?: any;

}

Can someone please help me out resolving this


Solution 1:

Make a copy of object using the Object.assign method and try again,

this.collectionPages = Object.assign([], this.collectionPages);
this.collectionPages.push(collectionPageDbModel);

Solution 2:

The solution proposed by Daniel certainly works for this case. The reason is Object Descriptors which every JS object have. You can check them out by calling Object.getOwnPropertyDescriptors(obj) and it will work for arrays too since (almost) everything is an object.

NGRX Store Selectors that were most probably used in the question modify object descriptors by using Object.defineProperties(obj). That is done to prevent any mutation of the data in the Store outside of the Reducer (which doesn't mutate state either, just creates a new one).

In general case you have to clone the object that you want to mutate:


import { cloneDeep } from 'lodash'

// ...

constructor(private store: Store<any>) {}

someMethod() {
  let someDataFromTheStore = cloneDeep(this.store.select(selectSomeData))
  someDataFromTheStore.myArray.push('...')
}


Both Object.assign and cloneDeep don't transfer descriptors to the new copy.

Object.getOwnPropertyDescriptors

Object.defineProperties