mobxjs / mobx-angular

The MobX connector for Angular.
MIT License
483 stars 59 forks source link

EXCEPTION: Uncaught (in promise): Error: Error in :0:0 caused by: [mobx] Invariant failed: no observable property 'someProperty' found on the observable object 'DomainStore@1' #8

Closed johnhamm closed 7 years ago

johnhamm commented 7 years ago

In my ngOnInit, I am calling observe(this.store, "currentGreeting") to react to the greeting value changing in my store. However, I am getting this error:

Error: Uncaught (in promise): Error: Error in :0:0 caused by: [mobx] Invariant failed: no observable property 'currentGreeting' found on the observable object 'DomainStore@1'
    at resolvePromise (polyfills.dll.js:18122)
    at polyfills.dll.js:18099
    at ZoneDelegate.invoke (polyfills.dll.js:17896)
    at Object.onInvoke (vendor.dll.js:26246)
    at ZoneDelegate.invoke (polyfills.dll.js:17895)
    at Zone.run (polyfills.dll.js:17789)
    at polyfills.dll.js:18155
    at ZoneDelegate.invokeTask (polyfills.dll.js:17929)
    at Object.onInvokeTask (vendor.dll.js:26237)
    at ZoneDelegate.invokeTask (polyfills.dll.js:17928)

Unhandled Promise rejection: Error in :0:0 caused by: [mobx] Invariant failed: no observable property 'currentGreeting' found on the observable object 'DomainStore@1' ; Zone: angular ; Task: Promise.then ; Value: ViewWrappedError {_nativeError: Error: Error in :0:0 caused by: [mobx] Invariant failed: no observable property 'currentGreeting' f…, originalError: Error: [mobx] Invariant failed: no observable property 'currentGreeting' found on the observable ob…, context: DebugContext} Error: [mobx] Invariant failed: no observable property 'currentGreeting' found on the observable object 'DomainStore@1'
    at invariant (eval at ./node_modules/mobx/lib/mobx.js (http://localhost/js/bundle.js:718:1), <anonymous>:2577:15)
    at getAtom (eval at ./node_modules/mobx/lib/mobx.js (http://localhost/js/bundle.js:718:1), <anonymous>:2407:13)
    at getAdministration (eval at ./node_modules/mobx/lib/mobx.js (http://localhost/js/bundle.js:718:1), <anonymous>:2424:34)
    at observeObservableProperty (eval at ./node_modules/mobx/lib/mobx.js (http://localhost/js/bundle.js:718:1), <anonymous>:498:12)
    at Object.observe (eval at ./node_modules/mobx/lib/mobx.js (http://localhost/js/bundle.js:718:1), <anonymous>:478:16)
    at EventComponent.ngOnInit (eval at ./src/components/event.component.ts (http://localhost/js/bundle.js:838:1), <anonymous>:32:16)
    at Wrapper_EventComponent.ngDoCheck (/AppModule/EventComponent/wrapper.ngfactory.js:22:53)
    at CompiledTemplate.proxyViewClass.View_EventComponent_Host0.detectChangesInternal (/AppModule/EventComponent/host.ngfactory.js:28:32)
    at CompiledTemplate.proxyViewClass.AppView.detectChanges (http://localhost/js/vendor.dll.js:51989:14)
    at CompiledTemplate.proxyViewClass.DebugAppView.detectChanges (http://localhost/js/vendor.dll.js:52082:44)
consoleError @ polyfills.dll.js:18048
_loop_1 @ polyfills.dll.js:18075
drainMicroTaskQueue @ polyfills.dll.js:18079
ZoneTask.invoke @ polyfills.dll.js:18001
polyfills.dll.js:18050 Error: Uncaught (in promise): Error: Error in :0:0 caused by: [mobx] Invariant failed: no observable property 'currentGreeting' found on the observable object 'DomainStore@1'
    at resolvePromise (polyfills.dll.js:18122)
    at polyfills.dll.js:18099
    at ZoneDelegate.invoke (polyfills.dll.js:17896)
    at Object.onInvoke (vendor.dll.js:26246)
    at ZoneDelegate.invoke (polyfills.dll.js:17895)
    at Zone.run (polyfills.dll.js:17789)
    at polyfills.dll.js:18155
    at ZoneDelegate.invokeTask (polyfills.dll.js:17929)
    at Object.onInvokeTask (vendor.dll.js:26237)
    at ZoneDelegate.invokeTask (polyfills.dll.js:17928)

Here is my DomainStore:

import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import 'shared/rxjs-small';
import { Observable } from 'rxjs/Observable';
import { observable, computed, action, autorun } from 'mobx';

import { plainToClass, Type } from "class-transformer";
import { UserModel } from 'models';
import { ApiService } from 'services';

@Injectable()
export class DomainStore {
      version = '<{version}>';

      @Type(() => UserModel)
      @observable users: UserModel[] = [];

      @observable currentUserId: number;
      @observable currentGreeting;

      @observable initialLoadComplete;
      @observable refresh = { events: false, config: false };

      constructor(private apiService: ApiService, private router: Router) {
            autorun("getUsers", () => {
                  let self = this;

                  if (self.refresh.events || self.users.length === 0) {
                        return self.apiService.get("users")
                              .subscribe(tables => {
                                    self.users = tables.users;
                              });
                  };
            });            
      }

      @computed get isLoggedIn() {
            return this.currentUser && this.currentUser.token && this.currentUser.token.length > 0;
      }

      @computed get currentUser() {
            return this.users.find(u => u.id === this.currentUserId);
      }
}

Here is my WelcomeComponent that calls observe from ngOnInit:

import { Component, OnInit, ChangeDetectionStrategy, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { Router, ActivatedRoute, Params } from '@angular/router';
import { observe } from 'mobx';

import { DomainStore } from 'stores';
import 'shared/rxjs-small';
declare var $: any;

@Component({
      selector: 'welcome',
      templateUrl: 'welcome.html',
      changeDetection: ChangeDetectionStrategy.OnPush
})
export class WelcomeComponent implements OnInit {
      constructor(private router: Router, private route: ActivatedRoute, public store: DomainStore) { }

      ngOnInit() {
            let self = this;

            this.route.params.subscribe((params: any) => {
                  this.store.changeCurrentEvent(params["site"]);
                  if (!this.store.currentEvent) {
                        this.router.navigate(["home"]);
                  }
            });

                        observe(this.store, "currentGreeting", change => {
                              if (change.newValue) {
                                    alert("Your greeting has changed.");
                                    $("#myModal").modal("hide");
                              }
                        });
      }
}

I have all of my components wrapped in <div class="jumbotron" *mobxAutorun>...</div> and they all have changeDetection: ChangeDetectionStrategy.OnPush set. I'm not sure why it is not detecting that the property is decorated with @observable. Am I missing a step?

adamkleingit commented 7 years ago

Hey, I made some changes in 1.2.0 (specifically made mobx a peer dependency).

Can you update and see if the error repeats? Thanks

johnhamm commented 7 years ago

I updated ng2-mobx to 1.2.0, as well as 1.2.1, and i installed mobx 3.0.2. I get the same error as above. When I tried updating to ng-mobx 1.2.2, I get this error:

EXCEPTION: Error in ./AppComponent class AppComponent - inline template:66:13 caused by: Cannot read property 'transform' of undefined

at View_AppComponent1.createInternal (component.ngfactory.js:310)
    at View_AppComponent1.AppView.create (vendor.dll.js:51784)
    at View_AppComponent1.DebugAppView.create (vendor.dll.js:52040)
    at TemplateRef_.createEmbeddedView (vendor.dll.js:37450)
    at ViewContainerRef_.createEmbeddedView (vendor.dll.js:37574)
    at new MobxAutorunDirective (eval at ./node_modules/ng2-mobx/dist/directives/mobx-autorun.directive.js (bundle.js:734), <anonymous>:20:40)
    at new Wrapper_MobxAutorunDirective (wrapper.ngfactory.js:7)
    at CompiledTemplate.proxyViewClass.View_AppComponent0.createInternal (component.ngfactory.js:21)
    at CompiledTemplate.proxyViewClass.AppView.create (vendor.dll.js:51784)
    at CompiledTemplate.proxyViewClass.DebugAppView.create (vendor.dll.js:52040)
    at CompiledTemplate.proxyViewClass.View_AppComponent_Host0.createInternal (host.ngfactory.js:16)
    at CompiledTemplate.proxyViewClass.AppView.createHostView (vendor.dll.js:51791)
    at CompiledTemplate.proxyViewClass.DebugAppView.createHostView (vendor.dll.js:52051)
    at ComponentFactory.create (vendor.dll.js:25638)
    at ApplicationRef_.bootstrap (vendor.dll.js:24063)

In the meantime, I've converted this whole app to mobx, and was wondering if there were any other mobx mechanisms I could use to trigger code when a mobx observable changes besides "observe" which isn't currently working?

ghost commented 7 years ago

Hey, which Angular version are you using? Can you share your code?

On Tue, Jan 24, 2017 at 5:33 AM, John Hamm notifications@github.com wrote:

I updated ng2-mobx to 1.2.0, and i installed mobx 3.0.2. I now get this error:

EXCEPTION: Error in ./AppComponent class AppComponent - inline template:66:13 caused by: Cannot read property 'transform' of undefined

at View_AppComponent1.createInternal (component.ngfactory.js:310) at View_AppComponent1.AppView.create (vendor.dll.js:51784) at ViewAppComponent1.DebugAppView.create (vendor.dll.js:52040) at TemplateRef.createEmbeddedView (vendor.dll.js:37450) at ViewContainerRef_.createEmbeddedView (vendor.dll.js:37574) at new MobxAutorunDirective (eval at ./node_modules/ng2-mobx/dist/directives/mobx-autorun.directive.js (bundle.js:734), :20:40) at new Wrapper_MobxAutorunDirective (wrapper.ngfactory.js:7) at CompiledTemplate.proxyViewClass.View_AppComponent0.createInternal (component.ngfactory.js:21) at CompiledTemplate.proxyViewClass.AppView.create (vendor.dll.js:51784) at CompiledTemplate.proxyViewClass.DebugAppView.create (vendor.dll.js:52040) at CompiledTemplate.proxyViewClass.View_AppComponentHost0.createInternal (host.ngfactory.js:16) at CompiledTemplate.proxyViewClass.AppView.createHostView (vendor.dll.js:51791) at CompiledTemplate.proxyViewClass.DebugAppView.createHostView (vendor.dll.js:52051) at ComponentFactory.create (vendor.dll.js:25638) at ApplicationRef.bootstrap (vendor.dll.js:24063)

In the meantime, I've converted this whole app to mobx, and was wondering if there were any other mobx mechanisms I could use to trigger code when a mobx observable changes besides "observe" which isn't currently working?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/500tech/ng2-mobx/issues/8#issuecomment-274692302, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUsQ0kNxtx-t6OcY28KYpMcEqNlu-5-ks5rVXEYgaJpZM4LmFUy .

-- Adam Klein CTO & Co-Founder Tel. +972-52-747-5633 blog.500tech.com http://blog.500tech.com meetup.com/angularjs-il

adamkleingit commented 7 years ago

Now I see your original error has nothing to do with ng2-mobx - you are using mobx' observe method directly. You can also use autorun and reaction instead of observe. And don't forget to dispose of the observers in the ngOnDestroy hook.

As for the error you are getting in ng2-mobx 1.2.2 - what Angular version are you using?

adamkleingit commented 7 years ago

BTW, you can use reaction instead of observe:

this.dispose = reaction(() => this.store.currentGreeting, (greeting) => {
  alert("Your greeting has changed.");
  $("#myModal").modal("hide");
});

// don't forget to dispose the listener:
ngOnDestroy() {
  this.dispose();
}
adamkleingit commented 7 years ago

Hey, updated version 1.2.3 to include AoT metadata, can you recheck the error you got? Thanks

adamkleingit commented 7 years ago

Closing this, if the problem persists please reopen. Thanks