Using Effects with Component Store
The refactoring work we did in the last example was a great way to get up to speed with most of the general tasks we will perform with Component Store. However, there is one important aspect we left out and that is effects.
We already briefly discussed an effect
in the first lesson:
An effect is generally used when we are performing some kind of asynchronous request that will need to update the state in some way - like fetching data from a server or, in this specific case, waiting for the result of a form submission to the server and updating the state appropriately.
We will actually be using multiple effects in the final application we will be building. We will talk through these in more detail as we actually implement them in the module on building the application, but I want to give you a sense of what they are right now.
Authentication Example
Let’s consider the scenario from the chat application we are going to build where we want to allow the user to log in.
At a simple level, we might not care about keeping track of the state of this log in request (e.g. handling success
and error
states differently). Let’s say all we care about is that if the login succeeds we want to navigate the user to the home
page.
We will be able to use a login
method that accepts a credentials
object:
this.authService.login(credentials);
This will return us an observable stream that will either emit the authenticated User
object, or it will error. Let’s consider how we would handle this authentication method without using an effect
.
We might set up a method like this:
login(){
const credentials = this.loginForm.value;
this.authService.login(credentials).subscribe((user) => {
if(user){
// navigate to home page
}
})
}
This looks pretty standard, but unfortunately we have to do a manual subscribe
here - which means, if we are being safe, that we should also make sure to implement some way to unsubscribe
. This isn’t that big of a deal… we’ve subscribed to things manually before. But it’s nicer to avoid it if possible. If we are already using Component Store, then an effect
can allow us to avoid this manual subscribe.
Instead of performing the login as we have above, we can instead create an effect
:
login = this.effect((credentials$: Observable<Credentials>) =>
credentials$.pipe(
switchMap((credentials) =>
this.authService.login(credentials).pipe(
tapResponse(
(user) => {
this.navCtrl.navigateRoot('/home');
},
(error) => console.log(error))
)
)
)
)
);
This is similar in principle to the updater
methods we were creating in the last lesson. To use the effect
above, we would call it like this:
this.store.login(credentials);
Notice that our effect
uses credentials$
as an input, which is an observable. Every time we call the login
effect with some credentials
as above, it will emit those credentials on the credentials$
stream. This gives us a way to handle the effect
being called multiple times before previous requests have finished.