Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NGXS Devtools doesn't represent the current state

So I started using NGXS and I have some difficulties to inspect my store via Redux Devtools

NGXS has devtools package that integrates with Redux Devtools Extension.

I've installed the latest version of the package (^3.2.0) and imported it into AppModule imports:

imports: [
  NgxsModule.forRoot([ProjectState, AuthState], {developmentMode: true}),
  ...
  NgxsReduxDevtoolsPluginModule.forRoot(),
]

On my AuthState, I did:

export class AuthState implements NgxsOnInit {

    constructor(private auth: AuthService) {}

    ngxsOnInit({dispatch}: StateContext<AuthStateModel>) {
      console.log('State initialized, now getting auth');
      dispatch(CheckAuthSession);
    }

    @Action(CheckAuthSession)
    checkSession({patchState}: StateContext<AuthStateModel>) {
      return this.auth.user$.pipe(
        tap((user) => patchState({initialized: true, user: user})),
      );
    }

When I open the console on Google Chrome, I do get the line

console.log('State initialized, now getting auth')

And the Auth Properties are loaded. Although, on Redux Devtools, I see only:

Redux Devtools

As you can see:

  • The action CheckAuthSession isn't dispatched
  • auth.initialized remains false even when I console log it, it's true.

The strange thing is that when I dispatch a new action, The extension does mention it and the state changes to what it was before the action. I'm not sure if that the correct behavior.

Update 1

When I add take(1) pipe before the tap in checkSession method, it somehow works. I have no idea why.

like image 834
Eliya Cohen Avatar asked Aug 18 '26 09:08

Eliya Cohen


1 Answers

The reason I didn't see my Action on the Devtools was that the action did never end since I didn't subscribe from it. In other words - if you have an action that returns an observable, it won't be displayed on Devtools until the subscription is being complete.

In my example, I didn't want to complete the subscription of my action handler, because I needed to listen to every change of my user$.

So to make my code reasonable, I kept the method unsubscribed, but I made a few changes:

  • I removed patchState({initialized: true, user: user}) from checkSession because then I wouldn't have any idea if the state has changed since the action won't be displayed because it never ends.
  • I added tap((user) => dispatch(new UpdateAuth(user)) inside the pipe of the user$ inside the checkSession method.
  • I created a new method called onUpdateAuth(user: User) which being called when UpdateAuth action is being triggered

like so:

@Action(UpdateAuth)
onUpdateAuth({patchState}: StateContext<AuthStateModel>, {user}: UpdateAuth) {
    patchState({user});
}

Took some time to figure it out, but after all - it makes much more sense like that.

like image 149
Eliya Cohen Avatar answered Aug 20 '26 23:08

Eliya Cohen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!