We're at the point where
we're sending a login request to the API
when the user submits the Sign In form,
and this works fine if the user enters
the right credentials,
but if they don't
the error will not be handled.
So let's go and improve this in our code.
We want to catch any errors that may occur
when we call the API.
And in this case we should
display an informative message to the user.
But let's think about how to do that.
We could simply display some text here
saying something like "Invalid credentials".
And maybe we could add some styles
to make the text red,
because errors are usually red.
But of course we only want to show that message
if there was an error, not all the time.
So we'll need to add
another state variable to our component,
let's call it "error".
And this could be a boolean property
that is initially "false".
But if an error occurs
we can call "setError" and change it to "true".
Incidentally, I'm catching all errors here
to keep it simple,
but ideally we should handle
different errors differently.
Like, if the request failed
because we couldn't connect to the API,
then we could display a different message
rather than "Invalid credentials".
Anyway, once we set that "error" flag,
we can conditionally display this message
only if the flag is true.
This way there is no error message to begin with,
but if we enter the wrong password
at that point we see "Invalid credentials" in red.
So far so good, but what happens
if we type the right password now?
The error message never goes away.
That's because we're setting
the "error" to "true" here,
but we never reset it to "false".
If the response is successful,
or, even better, as soon as
we re-submit the form,
we should reset "error" to "false".
This way when we click "Sign In"
the error message goes away.
Ok. We're handling the case
where our API request fails,
but there's another scenario we need to think about
any time we make an HTTP request.
And that's: what happens while
the request is in progress?
I'm going to add a helper function
to simulate a slow response from the server.
Since I'm running the Strapi server
on my local machine,
it will always respond very quickly,
but in a real world scenario
a user may be on a slow internet connection,
so there could be some delay.
This "sleep" function takes a number of milliseconds,
and will return a new Promise
that will resolve after that amount of time.
It's basically a way
to turn "setTimeout" into a Promise,
so that we can call "sleep" with say 2 seconds,
and then simply "await"
for that amount of time to pass.
This introduce an artificial delay
when making the API request.
And it means that when we click "Sign In"
nothing seems to happen
so I will try clicking again,
because I'm a very impatient user.
And the result is that
I've actually triggered 3 separate HTTP requests,
because I clicked the button 3 times.
Ideally as soon as the user clicks "Sign In"
we should disable this button
until we receive the response from the server.
And to do that we would need
another state variable to keep track of
whether we are "loading" a response from the server.
And if "loading" is true we should disable
the submit button.
But if you think about it
this "loading" state and the "error" state
go hand in hand.
We'll need to update both variables at the same time,
depending on the state of the request.
So we could change this to be
a single variable called "status",
that is an object containing a "loading" property
and an "error" property.
Both of which will be "false" initially,
now we have an error because,
the "error" variable no longer exists.
It should be "status.error" now.
Anyway, when we start a new HTTP request
we should call "setStatus",
and set "loading" to "true",
because we're waiting for the server response,
and "error" to false,
since we don't know yet
if this request will fail or succeed.
Then when we get a response,
if it's successful
we want to set "loading" to "false",
and leave "error" to false as well.
While if we get an error then
"loading" will still be "false",
but "error" should be "true".
Now we want to disable the button
if the request is in progress.
So let's check "status.loading",
and to keep it simple, in this case
I'll just show a "Loading..." message,
even though it would be nicer to display
some kind of progress indicator, like a spinner.
While if "loading" is false
then we can display this "Button".
Let's see how this works.
I'll have to re-enter the usual email address.
Let's start with an incorrect password.
And this time the button disappears
so we cannot click it multiple times.
And eventually we see
the "Invalid Credentials" message.
Now, let me clear the logs
and type in the right password.
It's loading.
And after the delay
we see the successful response in the logs.
Ok. So this is how we can handle
the "loading" and "error" conditions
when making an API request.
Note that all these different scenarios
are the same when making any HTTP request,
so we could actually extract this code
into some sort of reusable logic,
and in fact later in the course
we'll use a library that simplifies
some of this stuff.
Anyway, before I forget
let me remove this delay we added
just to simulate a slow response.
Let's quickly test that the app still works.
That's good.
The next step will be to decide what to do
after we successfully sign in.
What should we do with this
JSON web token returned by the server?
We'll talk about that in the next video.