ngxs / store

🚀 NGXS - State Management for Angular
http://ngxs.io
MIT License
3.54k stars 403 forks source link

🐞[BUG]: 'NGXS_SELECTOR_META' of undefined at app init after ng9/ngxs3.6 update > better error message #1631

Closed bertrandg closed 2 years ago

bertrandg commented 4 years ago

Affected Package

@ngxs/store

Is this a regression?

Yes, It was working with angular8.0.3/ngxs3.5.0 and the bug appears when I migrate to angular9.1.9/ngxs3.6.2

Description

I had a circular dependency warning from angular cli since long time. App was working well so I was not paying attention anymore.. (not a good idea i know!) When I updated angular & ngxs, I got Cannot read property 'NGXS_SELECTOR_META' of undefined error at runtime app init and have totally no idea where it comes from!

After some times, I manage to find a way to avoid the error without understanding it: I use TS classes to group ngxs selectors and in a specific one, if I use @Selector() decorator, I got the error at app init. When I use createSelector() instead of @Selector() in this class all the app is working well like before the upgrade.

After some extra debug session, I finally understand the circular dependency was the cause.

You can reproduce it in the stackblitz below. I know that's not really an ngxs bug but It would be great to have a better error message if possible.. :)

Initialy from this slack conversation with @markwhitfeld: https://ngxs.slack.com/archives/CA0NS79MG/p1591349955252500

🔬 Minimal Reproduction

https://stackblitz.com/edit/angular-ngxs-error-repro?file=src%2Fapp%2Fapp.component.ts You can toggle lines 13 & 16 to view when it happens or not.

Thanks for this great library and for the time you take to code & maintain it!

luchillo17 commented 4 years ago

I also got issues with this, but don't see a way to fix the circular dependencies, our states depends on services and vice-versa, is createSelector() the only way? image

stgrosshh commented 3 years ago

Same issue, when @Selector is used outside the state holding class (without any circular dependencies). Store version 3.7.2, Angular 11.2.13

markwhitfeld commented 3 years ago

@stgrosshh would it be possible to provide more information or a repro?

stgrosshh commented 3 years ago

@stgrosshh would it be possible to provide more information or a repro?

I will try to set up a small example showing the problem in a repo

arturovt commented 2 years ago

Since newer Angular versions emit ES2015 and not ES5 (where classes are downgraded to functions which are hoisted and might be used immediately), error messages become more meaningful. Classes are also hoisted, but might be used only after the code evaluation.

Testing it with Angular 11 and it throws Cannot access 'CurrentUserState' before initialization because this is how it looks like after the compilation:

class AppComponent {}

class CurrentUserSelectors {}

__decorate([Selector([CurrentUserState]), CurrentUserSelectors, "ips", null);

class CurrentUserState {}

It throws Cannot read property 'NGXS_SELECTOR_META' of undefined because ES5 variable is hoisted and equals undefined if accessed before the initialization:

var CurrentUserSelectors = function() {};

__decorate([Selector([/* undefined here */ CurrentUserState]), CurrentUserSelectors, "ips", null);

var CurrentUserState = function() {};

The createSelector approach works since it only captures the CurrentUserState reference, but doesn't access it immediately as opposed to @Selector() decorator.

I'm closing it as not an issue for now, since I don't see any issue in our codebase which likely might be solved.