So how can we leave these auth screen now if we are logged in or if we did sign up successfully?
Well that's not too difficult.
If we make it past this dispatching here without landing in the catch block,
so it's still here in the try block,
we can just call props.navigation.navigate just as we always did and navigate
to the different screen we set up in our switch navigator,
so in this case to the shop screen. So let's do that, let's simply go to shop and there for now as soon
as we do login successfully, which I'll now do, this loads
and we're here. Now I'll
get a warning here regarding some state update which couldn't be performed,
that's this set is loading state which now fails if we navigate away. The solution is simply we shouldn't
try to update the state on this screen if we're not on the screen anymore, so we can simply move that
into the catch block because we'll only need to reset loading if we have an error because that's the
only case when we stay on the auth screen,
otherwise we don't need to change the loading state because we're leaving the screen anyways. So with that,
we'll get rid of this as well,
if I now try this again,
here we go
and now we're in our main shop. Now we're still of course not utilizing the token,
so let's make sure we do that as well
and for that let's go to the auth reducer and add an initial state there which describes basically with
which state we want to start and what our general state shape is
and there I want to store the token which initially is null and I want to store the userId which initially
is null, so very basic initial state.
Then we can export the reducer function which takes that initial state and which also receives of course
an action and here I want to switch on the action type as always
and I got two cases I'm interested in right now.
One is the login action, so you need to import this identifier from the actions folder and the auth file
there and the other case is the sign up action,
so you need to import this identifier as well,
in other cases, I just want to return my state. So if we do login, I want to return a new state where
the token should be let's say action.token and userId should be action.userId
and that's the same update I need in sign up so we can just copy that over there.
Now of course we need to make sure that our action carries token and userId, so in the action creator
in the end of sign up here when I dispatch the sign up action, we need to add a token field and we need
to add a userId field.
Now the token can be gotten from the response data, there it's that ID token and the same here, resData
is not ID token but it's localId and you see that here in the log, localId,
this here is the userId and if you scroll up, ID token, that's the token. So that's what I dispatch here
and we can just copy that and use the same, almost the same for logging in,
the only thing that needs to change is this identifier and you could even unite login and sign up to
one combined authenticate identifier let's say because in a reducer, we're doing the same thing anyways.
So I just have it split up here to be clear that we have two different things in the end but the update
is the same, so we could definitely combine these two action types.
So with that, we're now storing the token and that's nice
but what do we need this token for again?
We need that token which we are now storing to access our API and for that, let's go to Firebase and to
database.
Keep in mind that when we set up this database, I mentioned that you should start in this test mode if
you remember. What this did is that it set up certain rules and you can check those if you click on the rules
tab. This controls who can read and write to your database
and right now this is both set to true which means everyone can read everything and everyone can write
everything.
That's of course typically not what you want, instead here I'll set both to auth unequal to null which
might look strange and this should be double quotes by the way here but this is Firebase syntax and
you can learn more about the rules here by clicking on learn more or simply google for Firebase real
time database security rules.
What this tells Firebase is that only authenticated users, so only users who send the request with a
valid token should be able to read and to write.
Now you could even argue that Redux should always be allowed,
we could set this to true and you could even be more specific regarding the rules so that you say Redux
from products is allowed,
Redux from orders is not
but again that's something you can check with the official docs.
I'll go with the setup where Redux is always allowed but writing is not.
So now for writing, we need a token,
otherwise we'll face a problem. If we login here and we're storing the token but we're not appending
it to requests right now,
you see we can load all data, that's fine
but you'll also notice that if I try to edit this and remove a couple of exclamation marks here, in the
end I get an error and that error is thrown because I'm not allowed to write and Firebase therefore
blocks the access and returns an error response.
So now we need to leverage the token which is stored in a reducer and actually append it to our outgoing
requests.
Now for that first of all, we need to register this reducer in our root reducer,
so in the app.js file, we need to import it, we need to import the auth reducer from the store and there
the reducers folder and there, the auth file and add it to combined reducers, maybe be here with the auth
key but of course you can use any key you want. That will allow us to then leverage this and access this
token but now we need to attach it to the outgoing requests, for example for products we need to attach
it to the request we send for updating products,
so that would be this request here. Now the way you append a request in Firebase can be found in the
official Firebase docs for the real time database user authentication here, there in the end what you
learned is that you can append a token to your outgoing request simply by adding that auth query parameter
at the end of your request URL.
So here in the end, we need to add question mark of equal
and then here, we need to have our token. Now how can we get access to the token here?
We're in the action creator which means we have no easy access to the store here, to the Redux store
or do we? Redux Thunk, that nice package which allows us to write this syntax with that function that
receives the dispatch function, that actually gives us something sweet.
We can also change this function a little bit and not just get dispatch but get a second argument as
well which is another function which gives us access to the Redux state,
so we get access to the current state of our Redux store. So if I console log the result of get state
here, let's see what that gives us
and to avoid errors, for the moment, here I'll just add an empty string so that we can test this code.
Of course, this will not work but we'll fix it soon, so let's see what's inside of that state if we execute
this.
So
time to login again real quick
and then go to the admin screen and try editing this which of course still will fail
but that doesn't matter because now if I do click here,
yes it fails but what you'll see is that here in the log, what we get is a full output of our complete
Redux store. This is our Redux store,
we get an object with our auth state slice which has yet another object with our token and with the user
ID, our card state slice, our orders state slice and our products state slice.
So this allows me to get access to my Redux store and get access to the token, so the token can be fetched
by executing getState.auth.token because this gives us access to our full Redux store,
this then gives us access to the auth slice and this to the token property which we're managing in that
auth slice. And now in the products action creator,
we can add this token here in the end. So here we can just replace this string with the token variable
which holds our token
and now if we save this, with this little change, if we now login again and later we'll also change this
such that we don't constantly need to relogin,
no worries. If we log in again, we go to admin, click on add it here and now we try this,
this works again because now the token is appended, Firebase validates it and determines that it's valid
because of course we haven't mingled with it,
it's a valid token and therefore this just works.
Now we don't just need the token when we update our products,
we also need it when we add a new product. So I'll copy that logic and add the same logic here, when we
create a product, I get my token with the help of that second argument which we can get here if we need
it, the get state function
and this allows me to change these single quotes to back ticks so that I can conveniently add that query
parameter here at the end with question mark of equals and equal that to my token.
So now we can create a product and update a product, deleting of course also is a write request,
so for delete product I'll do just the same, get access to my store with the get state function here and
then also add question mark of here at the end and add the token.
So that's one thing.
Now in the orders, it's a similar thing, there for fetching, we don't need it but for adding we do because
adding is a write operation.
So there, we get the state if we want to, we can extract the token from there with the same approach as
before and we can append this here and there, we'll actually also need the userId soon, so we'll take
care about this in the next lecture
but for now, just make sure you append the token everywhere
and now let's see how we can also make sure that orders actually really belong to our user.