Our blessing to do is log in form as show a spinner to our user so I'm sure that feels familiar and
might feel like to do is even We're doing a lot of the same stuff twice over.
But to be honest with you I'm really happy that we ended up rebuilding in log in form with redox.
After doing three act it really helps you get a feel for how each library behaves.
Anyways back to the task at hand showing a spinner on our logon form is going to be something would
kind of cool you know deceptively simple.
In other words we really don't need to over think the same.
As soon as our logon user action creator is called We will want to dispatch an action that somehow says
hey start spinner up please.
And then whenever we see a success or failure type come along that means OK well the authentication
Quest is complete we should resolve the spinner.
Or C we should turn off that loading flag and not show the spinner anymore.
So we're just going to depend upon the log in success log in user fail and a new action type that will
dispatch called log in user to figure out when the spinner should be running.
So let's give it a shot.
We'll start off by defining a new type inside of our type's file so my type's file add on export Konst
logon user.
So if you're getting a reasonable sense of the different action types that it might create for any type
of Ajax requests or any type of long or any requests that might fail or generally start off with just
logging user or you know kind of whatever the very base action is where ever I'm about to start.
And then for the success case and fail case I'll add on to additional types that just append success
and fail.
And so that makes that makes it really easy for me to understand like OK these are all related to logging
in the user and the different states that are social with it.
If I was can make any change here whatsoever I might do something like you know maybe start maybe.
That definitely makes sense.
It's really up to personal preference whether or not you can be really explicit about this first kind
of starting action type you're so totally up to you.
I could definitely see a case for putting on like log in user start there.
All right.
Back over my action creator here is logging user.
I'm going to immediately dispatch an action of type log in user whenever this action crater's called
will call dispatch.
With an action of type in user now we still need to import this.
We don't have the type inside this file just yet.
So I will scroll back up to the top and I'll make sure that I also include this action type at the top
in the import statement.
OK so now this is really starting to meet our requirements.
The instant that we try to log user in we're going to dispatch an action of type logon user.
Then whenever the request succeeds or fails we will dispatch the success or fail actions.
Well one thing I really want to point out in particular is that we are going to use this logon user
typewrite here to start our spinner.
And so you might be a little bit tempted to do something like you know an action of tide start spinner
or something like that and I would really encourage you not to go down that path.
The reason for which is that at some future point in time when you are coming back to this code after
some long break or whatever it might be you see a action of type like start spinner when you don't quite
know when that thing is going to be dispatched right.
You don't really quite know by just looking at the actions name you know what it might do.
You know you might you it gives you a reason or idea that's going to serve the spinner but you don't
really know when it's going to be dispatched.
So it's something like logging user it's very clear.
OK this is going to dispatch whenever I'm about to log in the User very clear what it does is a little
bit more of a mystery but I would rather have to figure that out than have to figure out when the thing
gets called.
All right so now we can flip over to our producer.
I'm going to pull in my log in user type and then we'll add on another case statement to handle this
type.
So case log in user so now inside of here I want to take all of my existing state and I won't want to
set the loading flag to true.
So we don't have one just yet.
Let's initialises property.
Again we don't have to do this.
I'm choosing to do it so that any engineer in the future is going to have a reasonable idea of what
all the different pieces of state are inside this reducer.
So now we've got logged in user loading.
True.
Another thing that I'm going to decide to put in here and this is kind of you know I'm just thinking
ahead for my for my program for my app here.
Chances are that whenever I start up the log in process if there's any existing error message I might
want to zero that out as well.
You know I might want to clear out the error message and this makes a lot of sense because if I attempt
to log in once and I fail and then I'd say like you know change my password again and I hit log in again.
I want the user to understand it like you.
OK.
Yes we understand that you are trying to log in again.
We will clear that error message because otherwise you're going to think that your app is just you know
doing nothing whatsoever.
All right so now we're going to get this loading true flag.
We will also make sure that we clear loading true whenever we hit the success case or the fail case.
So whenever we hit success on a flip leading to false and whenever we hit the fail case I'm also going
to change loading to false as well.
Now this line right here is getting a little bit long so if you want to do some newline characters in
here that's totally fine.
I think I'm just going to let it kind of hang out for a little bit.
OK.
So we've got our loading flag right now and we are properly toggling it from true to false between all
of our different states.
Let's flip over to our blog and form.
So here's my log in form.
I'm now going to add that loading flag to my map state to prop's function and then we're going to place
the button inside the log and form along with the spinner so I'll scroll down to the bottom find my
map state to prop's here's where we put all of our properties off the Auth. state object.
So also pulling this new loading flag that we're maintaining and I'll make sure I pass it down to the
component as well.
Next at the very top I will import my spinner for my common components.
Remember this is one of those compounds that we've made and pulled through from project to project.
And then inside of my render method I'm going to find the button.
All right here it is right here and we want to move this button to a helper method where we're are going
to say instead of always showing the button right here we will call the helper method and decide whether
or not we want to show the button or the spinner depending on that loading flag.
So this should feel pretty familiar because we did it once already in the Auth. project.
So we'll say This rendered button we're going to take the same exact approach here and I'm going to
cut this button tag right here.
Let's cut it out and then we'll define render button as a helper method.
So a rendered button.
Then if this docked props start loading.
So if we are loading return early and so a spinner and I wanted to be a size large Otherwise we can
return that bit of button GSX that we just cut out.
So there we go.
I got my rendered button for loading.
So the spinner.
Otherwise show our button.
Cool.
I think we're all set.
I think we're ready for a test in the simulator.
I'll do my refresh now if I've put in test at test dot com and put in a bad password to start.
So I'll put in a bad password we get the spinner we see authentication failed the password goes away
because we want to clear that password out so the user kind of doesn't keep on just trying to like say
oh maybe it was like you know that very classic you know password one oh that didn't work OK.
Two three.
You know what that type of kind of funky situation.
So let's now log in appropriately.
Now the instant that I attempt to log in here I'm going to expect to see the error message go away.
I don't expect to see a spinner start up and then I'm going to expect to see this button come back when
loading is all complete.
There we go.
Just all we expected.
Now again this is a situation where we don't really have to flip the spinner back to a button that much.
Right.
Because in theory when the user loads or logs in successfully We're going to redirect them away from
this form to some type of like you know logged in page inside our app.
Nonetheless I think it's really good practice just to make sure that you can reset all of your form
attributes before you know something it's a little messy or dirty.
Speaking of which one more thing I want to point out here.
Speaking of you know resetting form attributes I'm not going to do this because we're not going to really
have a log out feature in this app.
You know we covered it earlier in the authentication app so I've got a reasonable belief that you know
how to put the log out functionality together yourself.
But one thing I want to point out.
Is that if for some reason we navigate away from the screen and then come back to it and we're going
to be covering navigation here very shortly the values of these inputs are stored in the reducer right.
That's where they are stored.
So if I go away from this form and then come back to it those values are still going to be in the reducer.
And so I would see if I came back to this form right here I would see an email and password still in
the form which is really not expected behavior at all.
So one way that I might choose to solve this is to flip over to my auth reducer and I could say I'm
here hey whenever someone successfully logs in so I'm going to put some new new lines in here whenever
someone successfully logs in.
That's great.
You know we've got their user user model now but I don't want to have like that stored or kind of cached
email or password in the form anymore so I might choose to also reset the email and the password like
so.
So now someone navigates away from the form and comes back to it.
They won't see their e-mail and password prefilled in there.
Now the one thing I want to point out now is that if you look at the signature of this return statement
right here we are essentially redefining every single property on our state objects.
Right we've got like dot dot dot state which might have an air loading e-mail whatever has all that
stuff on there but we're resetting all of that right here.
So I think we might bill to actually clean this up a little bit.
I'm going to remove all of those extra attributes.
I'm going to condense down to just dot dot dot state and user.
And then I will also spread it.
Here's the tricky part.
Initial State.
So I'd say take all of our existing state you know whatever it might be.
Who knows maybe we add in some additional properties in the future and we don't reflect them initial
state.
You know this initial dot dot state right here is just future proofing this for ourselves.
Then reset all the state and order redo sir.
And then on top of that throw in our user model as well.
So let's see how this works now it will be our last test.
I know this is turning into a long section but I really wanted to add in this last thing in here.
So now if I do one two three I'm going to see my error message.
But if I hit password when I logged in successfully perfect the form resets I go back to no spinner
no error message.
Everything is back to just very empty.
And so if a user ever comes back to this form they're not going to see the proof.
Pre-filled email and password.
OK wriggling S..
Let's see.
I think we're all done here.
Let's continue the next section.
I think we're ready to move on to navigation