5

There might be someone who knows why NGXS state cannot change inside of HttpClient POST request.

ctx.patchState()

Only works outside HTTP POST request.

    @Action(SignIn)
    signin(ctx: StateContext<AppStateModel>, { payload }: SignIn) {

        // ctx.patchState({isLoggedIn:true}) this works!

        return this.api$.signin(payload)
            .pipe(
                tap((user: User) => {
                    console.log(user);
                    ctx.patchState({ isLoggedIn: true })

                })
            )
            .subscribe(
                (user: User) => {
                    ctx.patchState({ isLoggedIn: true })

                }
            )
    }
R. Richards
  • 24,603
  • 10
  • 64
  • 64

1 Answers1

6

Actually, the state is changing, but you don't see it because you return subscription that hasn't been completed. In other words - You'll see the action being dispatched once the subscription of the returned observable completes.

As mentioned in the comments, the returned observable of the actions are being subscribed behind the scene, so there's no need to subscribe to it again.

After that being said, you can pass take(1) in the pipe.

What it does, it completes the subscription of the observable after it triggered once.

    @Action(SignIn)
    signin(ctx: StateContext<AppStateModel>, { payload }: SignIn) {
        return this.api$.signin(payload)
            .pipe(
                take(1), // <-- Add that
                tap((user: User) => ctx.patchState({ isLoggedIn: true }))
            );
    }
Eliya Cohen
  • 10,716
  • 13
  • 59
  • 116
  • Question - is the take(1) really necessary or just 'good documentation'? If the signin API is talking to an external service it doesn't seem likely that it will emit more than one value and complete anyway. I might put it in anyway to indicate that I'm only interested in the first value emitted... – Rich Duncan Aug 27 '18 at 16:49
  • As long as you don't need to subscribe to an observable all the time, it is recommended to complete the subscription once you don't need it anymore to avoid memory leak. Further information - https://stackoverflow.com/questions/38008334/angular-rxjs-when-should-i-unsubscribe-from-subscription – Eliya Cohen Aug 28 '18 at 08:00
  • Thanks - I followed your link and then found this, which is a definitive statement here: http://reactivex.io/documentation/contract.html When an Observable issues an OnError or OnComplete notification to its observers, this ends the subscription. Observers do not need to issue an Unsubscribe notification to end subscriptions that are ended by the Observable in this way. – Rich Duncan Aug 28 '18 at 16:11