Maximilian: Now at the moment,
I'm sending this Http request
and I'm not doing anything with the response
and I'm also not handling potential errors.
That's of course something which we might wanna avoid.
Now, to handle the response and potential errors,
I edit a new component,
which you'll find attached in a zip file,
the notification component
which you should put into your UI folder.
It's a simple component
that displays a title and the message
and that can assume different CSS classes
based on a status prop.
And then it's simply a little a bar at the top
which will show up,
which can either say something like sending request,
or once it's done it can tell us if it was a success
or if we have an error.
Now, to use it with our current approach in App.js,
here on fetch, we can simply add then or we use async await.
Since we were in use effect though,
we should not add async here,
but instead wrapped us in a separate fetch then
and that's actually what I'll do here
so I'll add a new function here.
Instead of user fact send cart data.
It's a simple function which will hold this code
but it's now asynchronous.
So we can await this to get our response.
And then when we get the response here
we can get our response data
by waiting response dot Jason like this.
And we can also check if the response maybe not okay.
And if it's not okay, we have an errors.
So then we might want to throw a new error here.
Where we say, sending cart data failed
or anything like this.
If we make it past this line
however we know that we were successful.
And then we know that we,
well should show that success notification.
And actually we also want to show
the notification right from the start
when we start sending.
Now for this we could import use state
and set up some local state and this component,
some is loading state and maybe an error state.
And we set dose States
as part of our Http requests cycle here.
And we then use those states to conditionally
rendered the notification component
with the appropriate content.
We could do all of that,
there would be nothing wrong with that
and it would be a good way of handling this.
But since we already have a UI slice here in Redux
why not use that?
Why don't we add more to the state
we're managing here with Redux
and we managed the notification,
which we're showing with help of Redux now.
For this I'll add a notification property
to initial state and I'll set it to null initially,
so that initially we have no notification.
But then we can add a new reducer
which we could call set notification
or show notification maybe,
where we get our state
and where we also use the action
because I expect some action payload here
because the kind of notification that should be shown
should be encoded in the action as a payload.
And we then there for a set state notification equal
to an object let's say,
of course the exact structure
is up to you since it's your code.
But also to an object
where I have a status key
which I expect to get from my action payload.
Let's say dear, we all expect the status property
and status could be something
like pending error and success.
And then we also expect a title let's say
which we also get from the action payload and a message
which we all know I expect
as a property on the action payload.
So we set our notification to such an object.
Now we want to dispatch does show notification action
when we start sending the data
when we're done with the data and if we have an error.
So therefore we can import use dispatch from React Redux
to get access to that dispatch function
by executing use dispatch.
And we import our UI actions from store, UI slice.
And then, and here in user fact, when we sent the card data
we initially dispatch UI action start show notification
and pass an object to show notification
where we set the status to pending let's say,
because we're currently saying
sending the request, the title to sending maybe
and let's say the message to sending cart data.
That could be the, the notification we wanna set now.
Now I also want to dispatch an action once we're done.
So once we got the response data.
I actually don't care about the response data in this case,
because for sending the card
I'm not interested in any response.
So we don't even need to get to the response data
instead knowing that we don't have an error is enough.
So then I want to dispatch a new notification
where the status is success
and it should be success because I'm using
that instead of the notification component
then to adjust the CSS classes.
So I'll set it to success,
have a title of success maybe.
And then we could say sent cart data successfully.
Now, if we have an error, I also wanna dispatch
and I'll do that instead of throwing an error
I'll instead dispatch a new action where I say error
and then have error here as well.
And here we could say, sending cart data failed, like this.
Now this will not handle all kinds of errors though
because we could also have an error
from some other part in this code
instead of just having an invalid response status.
And therefore I'll actually cut this
and go back to throw new error
and simply go below this send cart data function
which we defined, executed here,
and then call catchier to catch any errors
that might be thrown from inside this function.
Since it's an async function,
this send cart data function returns a promise,
so we can call catch on it.
We catch any errors we might be getting here.
And I then dispatch my show notification action
with the error in here.
And that then handles all kinds of errors that could occur.
Now I'm getting some yellow squiggly lines here
because cart is no longer the only dependency year.
The dispatch function is actually also a dependency now.
The dispatch function created by use dispatch.
We can safely add it to the dependencies array
because React Redux will ensure
that this is a function which will never change.
So this patch will never trigger this effect
to rerun only card changes will.
Nonetheless for completeness sake we should add it
to get rid of these yellow squiggly lines.
And now we are dispatching different notification states
depending on the current status we have.
With all those changes made, we can save this
and we now just need to use this new notification UI state.
And I also want to use data and app JS.
I already import you as selector.
And now I just want to also select my notification status
with use selector from the state.
So we're drilling into state dot UI dot notification.
I get that notification property.
And that's either null initially,
or it's an object as set by us as this patched by us
and therefore now we can use notification
to conditionally rendered a notification component
and to then provide extra data
to the notification component.
Now for rendering the notification component,
I'll start by importing fragment from React
because I want to render the notification components
side-by-side to layout
since adjacent JSX isn't allowed I'll use fragment
and wrap that around layout
so that here we can then add notification.
And of course they offer import the notification
component import notification
from slash components, UI notification
and only render notification if we have a notification.
So now I'll check if notification is truthy
and only if it is I render notification.
And then I set the status equal to notification dot status.
I set the title equal to notification dot title
and I'll set the message equal
to notification dot message.
With all that's done if we now save that code,
I get an error, cannot read property UI of undefined.
Yeah, because here I'm using use states.
I auto completed that incorrectly.
That would be used selector.
We don't need use state here.
So let's switch this to use selectors save again.
And now we have the notification right
from the start when I reload.
The reason for this is that initially
sends a cart to request
if I reload and I have the network tab open
we see there's a cart request being sent to firebase.
So the good thing is we see the pending state briefly
and then the success States.
So that works.
But of course we don't want to send
the cart stayed right at the beginning
because dead will then always override our existing cart
on the backend with an empty cart when the app loads.
Working around that as simple in app JS
I just want to make sure
that we don't send the cart
when this runs for the first time.
And for implementing this
we could add a variable here outside of our function
maybe name it is initial and set it to true.
And I define it outside of my component function
so that this does not change.
And it's not re initialized
if the component renders again,
instead this will be initialized
when this file is parsed for the first time.
So when my application started therefore
and that's exactly what I want
and we can use his initial here
to check if his initial
and if that's the case I'll return.
I'll not continue so I'll not send my cart data.
However, I don't just want to do that
but I now also want to set his initial two false
so that this will never happen again
but it only blocks this cart data
from being sent the first time this effect executes
so when the application started.
With that addition made here,
if I reload we don't see the notification.
We're not sending that cart request
but if I add something to my cart,
we have the pending state
and then the success state, and that works just fine.
Now let's also test the error state
by removing dot Jason and therefore breaking that.
If we now save this and reload
if I add to cart, we see the error state.
So that is working exactly as it should.
And therefore let's bring back dot Jason.
Now, if we reload, we can send data to the cart again.
So that is working, but of course we're never
fetching that card from firebase
and therefore after a reload
we still start with an empty cart again
because we're not using that firebase data.
And of course, that's only one way of handling it
putting all that side-effect logic into our component
and that's perfectly fine, but there is an alternative.
And of course we also want to fetch data.