Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError: Cannot assign to read only property 'expanded' of object '[object Object]' #664

Closed
jrmcdona opened this issue Dec 20, 2017 · 8 comments

Comments

@jrmcdona
Copy link

jrmcdona commented Dec 20, 2017

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ x] Bug report 
[ ] Feature request
[ ] Documentation issue or request

What is the current behavior?

I upgraded my Angular packages and this started happening.

When I look at the object in the chrome console I see this:
Value below was evaluated

Trying to do something with the object fails with this:
TypeError: Cannot assign to read only property 'expanded' of object '[object Object]'

Expected behavior:

No error when I try to change the property on the click event after the ngFor with async pipe loads.

Minimal reproduction of the problem with instructions:

I am calling the store:
this.threads$ = this.store.select(fromEvents.selectAllEvents);
I am binding to the template:

 <div *ngIf="(threads$ | async)?.length>0">
                <div class="thread-list">
                        <div *ngFor="let thread of threads$ | async">
                                <app-thread [thread]="thread"></app-thread>
                        </div>
                </div>
        </div>

My app-thread.component.ts is here and notice the click event, because that is where it fails.
@input() thread: Thread;

My app-thread.component.hmtl is here and notice the click event, because that is where it fails.

....

I try to change a propery on the thread model after it has rendered and this is where it fails:

    public showQuestionFullDetail(item: Thread) {
        item.expanded = ! item.expanded;
    }

My Thread model:

export interface IThread {
    id: string;
    dateTime: Date;
    question: string;
    channel: string;
    category: string;
    expanded: boolean;
    newContent: boolean;
}

export class Thread implements IThread {
    constructor(public id: string, public dateTime: Date,
                public question: string, public channel: string,
                public category: string,
                public expanded: boolean,
                public newContent: boolean) {
        this.id = id;
        this.question = question;
        this.channel = channel;
        this.dateTime = dateTime;
        this.category = category;
        this.expanded = expanded;
        this.newContent = newContent;
    }
}

Version of affected browser(s),operating system(s), npm, node and ngrx:

Angular: 5.1.1
... animations, common, compiler, compiler-cli, core, forms
... http, platform-browser, platform-browser-dynamic, router
... service-worker

@angular/cli: 1.6.0-rc.2
@angular/language-service: 5.0.2
@angular-devkit/build-optimizer: 0.0.36
@angular-devkit/core: 0.0.22
@angular-devkit/schematics: 0.0.42
@ngtools/json-schema: 1.1.0
@ngtools/webpack: 1.9.0-rc.2
@schematics/angular: 0.1.11
@schematics/schematics: 0.0.11
typescript: 2.4.2
webpack: 3.10.0

Other information:

Object is showing Value below was evaluated in chrome console
image

 "dependencies": {
    "@angular/animations": "^5.0.0",
    "@angular/common": "^5.0.0",
    "@angular/compiler": "^5.0.0",
    "@angular/core": "^5.0.0",
    "@angular/forms": "^5.0.0",
    "@angular/http": "^5.0.0",
    "@angular/platform-browser": "^5.0.0",
    "@angular/platform-browser-dynamic": "^5.0.0",
    "@angular/router": "^5.0.0",
    "@angular/service-worker": "^5.0.0",
    "@ngrx/entity": "^4.1.1",
    "@ngrx/store": "^4.1.1",
    "@ngrx/store-devtools": "^4.1.1",
    "core-js": "^2.4.1",
    "moment": "^2.19.3",
    "rxjs": "^5.5.2",
    "zone.js": "^0.8.14"
  },
  "devDependencies": {
    "@angular/cli": "1.6.0-rc.2",
    "@angular/compiler-cli": "^5.0.0",
    "@angular/language-service": "^5.0.0",
    "@types/jasmine": "~2.5.53",
    "@types/jasminewd2": "~2.0.2",
    "@types/node": "~6.0.60",
    "codelyzer": "~3.2.0",
    "jasmine-core": "~2.6.2",
    "jasmine-spec-reporter": "~4.1.0",
    "karma": "~1.7.0",
    "karma-chrome-launcher": "~2.1.1",
    "karma-cli": "~1.0.1",
    "karma-coverage-istanbul-reporter": "^1.2.1",
    "karma-jasmine": "~1.1.0",
    "karma-jasmine-html-reporter": "^0.2.2",
    "ngrx-store-freeze": "^0.2.0",
    "protractor": "~5.1.2",
    "ts-node": "~3.2.0",
    "tslint": "~5.7.0",
    "typescript": "~2.4.2"
  }
@jrmcdona
Copy link
Author

Ok, the issue is with store freeze
export const metaReducers: MetaReducer<State>[] = []; // !environment.production ? [storeFreeze] : [];

When I comment out storeFreeze in the line of code above it works. What is not compatible with store Freeze in my set up?

I am not using @ngrx/router-store so this shouldnt be an issue for me per this thread:
#183

@MattiJarvinen
Copy link

You shouldn't alter store values instead changes to store values should be handled with actions. Values should be immutable.

@jrmcdona
Copy link
Author

shoot, that is a dang good point. Got ahead of myself it seems. I will go back and do that!

@MattiJarvinen
Copy link

Also you should probably have expandedMap as thread.id array instead of individual thread.expanded. This would keep the "db" of thread entities clean of presentational values.

Depending on other needs, like persistence of expanded property when going back and forth in views you could leave that expandedMap in container component instead.

@jrmcdona
Copy link
Author

jrmcdona commented Dec 21, 2017

@MattiJarvinen-BA that is a good point. I was wondering about that and makes sense to keep presentational value out of entities db. Good suggestion, I will look into that.

@huantaoliu
Copy link

You shouldn't alter store values instead changes to store values should be handled with actions. Values should be immutable.

use {...object}

@Tecayehuatl
Copy link

Check your module settings, do you have something like this?

StoreModule.forRoot(reducers, {
		metaReducers,
		runtimeChecks: {
			strictStateImmutability: true,
			strictActionImmutability: false,
			strictStateSerializability: true,
			strictActionSerializability: true
		}
	})

I disabled the strictActionImmutability property, another alternative is to run ng serve --prod with the --prod flag, if you only run ng serve you need to set to false the strictActionImmutability property in your runtimeChecks object

@jeremywib7
Copy link

Check your module settings, do you have something like this?

StoreModule.forRoot(reducers, {
		metaReducers,
		runtimeChecks: {
			strictStateImmutability: true,
			strictActionImmutability: false,
			strictStateSerializability: true,
			strictActionSerializability: true
		}
	})

I disabled the strictActionImmutability property, another alternative is to run ng serve --prod with the --prod flag, if you only run ng serve you need to set to false the strictActionImmutability property in your runtimeChecks object

for me, also set strictStateImmutability to false

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants