- Read Tutorial
- Watch Guide Video
Now that we have our current user having the ability to provide global state for the user, we also have the ability to set the current user. And we're going to start talking about that in this guide. And so what we're going to do is we are going to go back and kinda think about the logical flow of how our application is going to work.
So just imagine that somebody has downloaded your application. It could be this one, it could be one you build in the future. When the user clicks on the icon on their Android or iOS device, we want to think about what is going to be triggered when that occurs? Well, in our case one of the very first things we want to know is if the user is authenticated or not, because if they are, we don't want to show them the registration or the login screen. Instead, we want to take them right to their feed. If they are not authenticated, then we want to show them these types of authentication screens. So, how can we build in that type of divergent flow? Well, that's what we're going to start building out in this guide.
So I'm going to create a new component, a new screen here. So let's go down to our screens and inside of our auth screen, I'm going to create a new file here and we're going to call this the AuthLoadingScreen.tsx and then let's start building this AuthLoadingScreen out. So this is going to bring in a number of elements. So we're going to bring in react. We're also going to use a few hooks in this guide. So we're going to use the useEffect hook and we're also going to use the useContext. We're not going to have to use state in this one and those are all going to be from react. Now, we are also going to need to grab a view from react native. So I'm going to save import view, make sure you do that in curly brackets, from react native.
AuthLoadingScreen.tsx
import React, { useEffect, useContext } from "react"; import { View } from "react-native";
And then lastly, we're going to use something that is very cool. We are not going to actually have it fully implemented in this guide, but we are going to at least build the foundation for it. And that is going to be our secure store. So, if you think about how the device works, if we want the ability when a user presses the button and opens our app, if we want the ability to see if that user is authenticated, we actually need to store something on the device. And so what we're going to do is we're going to secure if the user has registered or they've logged in successfully, we're going to take a secure encrypted token and we're going to store that on the hardware, on the device itself and then as the user logs in, or as the user opens the app, we're going to see if that first, if that token is there and then we're going to pass that token up to the API to see if the user is who they say they are.
So, to do that we can open up our package JSON file. And what we're going to want here is we want the expo-secure-store. So we can just copy this and the way I'm going to import this, and you've seen me do this a few times. I'm going to say I want to import star, which means I want to import all from, or as secure store from expo secure store. That simply means in typescript language and you're really going to only see or typically you're only going to see this import star as secure store, that just means that I want you to bring me everything in that expo secure store library and I want you to name it this so that I can call it from within my component.
AuthLoadingScreen.tsx
import * as SecureStore from "expo-secure-store";
So, with all of that built out, let's build out our interface. So because this is going to be a screen, this has access to the navigation. So with that I'll say I want to get the IAuthLoadingScreenProps interface and then that's going to take in the props of navigation and you can reference this in any of the other screens. So it's going to take navigation which is an object and then the navigate function and navigate function is going to take in the screen name which is a string and then it's going to return void. Once again, this is just the interface. This is just so that we can when we call these elements inside of our component, you'll know what we have access to.
AuthLoadingScreen.tsx
interface IAuthLoadingScreenProps { navigation: { navigate: (screenName: string) => void; }; }
So with that interface built out, let's start building the component itself. So I'm going to say export default and then my props are going to match up with that auth screen loading props and it's going to be a fat arrow function. Now this is going to be an interesting one. So I don't want this to throw you off. All that we're going to return as far as what users are going to see is an empty view tag. So I'm going to say view just like this.
AuthLoadingScreen.tsx
export default (props: IAuthLoadingScreenProps) => { return <View />; };
So what in the world's going on here? So technically the users aren't even going to see anything and the reason for that is because this component or this screen its only job is to see if a user is logged in or if they're not and depending on what the answer to that question is, it's simply going to redirect the user based off of what the user's authentication status is. That's all it's doing. So we're technically just showing an empty screen here while we're checking on if the user is logged in or not. So that's all we're doing.
So, now let's also start in bringing our context. So let's import the context. So I'm going to say import current user context from dot, dot, ope, not form, from. And then inside of here, ../../contexts/CurrentUserContext. My auto correct's really not liking me today. Okay, so we have that and here all we're wanting to get out of the current user provider is the ability to set the current user. So I'm going to copy that and now I'm going to do something very similar to what we did in our feed screen if you remember when we were getting, or not the feed screen, which one was that? The auth screen. Where we perform de-structuring so we use the use context. It sent the context into it and then we grabbed current user. Here we're doing the same thing, except I only want the ability to set the current user. So I'm going to say const, use de-structuring for set current user and then I'm going to set that equal to use context and the current user context.
AuthLoadingScreen.tsx
import CurrentUserContext from "../../contexts/CurrentUserContext";
AuthLoadingScreen.tsx
export default (props: IAuthLoadingScreenProps) => { const { setCurrentUser } = useContext(CurrentUserContext); return <View />; };
So what that's going to give us the ability to do is we're going to be able to call the API, so we're going to be able to call the API and say hey, is this user who they say they are or are they logged in or not? If they are, then we're going to send them directly to the feed screen. If not, we're going to send them to the authentication screen and if they are who they say they are, we're also going to have the ability to store the current user's data inside of our provider.
Hopefully it's starting to make a little bit of sense on how all of these pieces are communicating with each other and how they're passing data back and forth. And if it's still a little bit blurry, do not worry. We're going to keep on working through it.
So, now that we have access to setting the current user, now what we're going to do is we're going to create a function here. So I'm going to say, const, check login and this is just going to be a regular fat arrow function and we're going to have to do one little thing here. I'm going to let an error pop up here for a second so that you can see what I'm doing. So the first thing we need to do is see if the token is set. So I'm going to create a variable to store the token. So I'm going to say const token equals and then I'm going to use a wait and then secure store dot get item async and then so what we're going to do here is we can call right now is the moment, we're going to name whatever our token is going to be called. So, in this case let's just call it the memipedia, secure token.
Okay, now you see we have a little error here and if you read the error it says, "'await' expressions are only allowed "within async functions and at the top level of modules." If that doesn't really make a lot of sense, what that essentially means is you can't call a wait and secure store expects you to do this. So what we're saying here is I don't want anything else in the program to run until after this happens and so in order for this to work, we need to call async and say that this is an async function. The way you do that is right next to the parentheses up here, you type async if you know how to spell. There you go, and you can see that that's now working.
AuthLoadingScreen.tsx
const checkLogin = async () => { const token = await SecureStore.getItemAsync("memipedia_secure_token"); };
Okay, that's kind of cool. So, now we have this async function. What's happening here? Well, we're telling the program that we want to go and get this token. So the way it works is in one of the next few guides, we're going to see how we can set the token when the user is logged in. What's going to happen is we're going to look on the device for a token named this. So we have the ability to set our own unique name for the token. We are then going to go and we're going to call that token and we're going to say on the device, hey, is there a token called memipedia secure token? If there is, then it'll get passed up to us and it'll get stored in this token variable. If not, then we're going to know the user definitely is not logged in, because they don't even have a token stored on the device.
So, let's now build out a API function. So, I'm going to say if there is a token, then if that's the case, then we're just going to verify that the user's logged in. So in this case, I'm just going to add a to do then I'm going to say call API to ensure logged in. And then that's going to eventually allow us to get access to the API and to that current user. If there is no token here, though, so if this is nill or null, and that means that we do not have that in place, we know the user is definitely not logged in. We don't have to make an extra call to the API, because that's just a waste of time. We know for a fact the user needs to log in. So if that's not the case else, now we want some other stuff to happen. So what do we want to have happen? We want to redirect the user to the auth screen and then from there, we want to make sure the current user is set to null.
So let's do those two things. I can say props dot and navigation dot navigate and then we pass in a string and for this one it's just called the auth screen if I remember correctly. And then I want to set the current user and I want to set them to null. And I'm going to actually put that first.
AuthLoadingScreen.tsx
const checkLogin = async () => { const token = await SecureStore.getItemAsync("memipedia_secure_token"); if (token) { // TODO // call API to ensure logged in } else { setCurrentUser(null); props.navigation.navigate("Auth"); } };
So what's going to happen here just to kinda look at the flow, we're going to say is the user, do they have a token named memipedia secure token on the device? If so, we'll eventually call the API to make sure that the token is still valid and that it's real and you don't have someone trying to hack into the system and say they found the name of the token and they just added a bunch of random characters. We want to make sure it's actually valid, so we will make an API call to ensure that. If not, we know the user's not logged in so we'll ensure the current user's set to null so it's not going to be anything and then we're going to redirect the user to the auth screen. So that is all we're doing.
Now, the last thing we're going to do in this guide, and then we'll take a little break, is we're going to make sure that this function runs as soon as the screen loads up. So to do that, we're going to use an effect hook. So you write useEffect and it has two parens. The first one is because useEffect is a function. The next one is we're not passing in any arguments so this is going to be an anonymous function here. And then we're going to call check, or yeah, check login, and make sure you call it with parens and then one other thing here with useEffect. After the curly braces, type a comma and then brackets and the reason for that is because the way useEffect works, if you're not that familiar with it, if I were to leave this off, useEffect would run all the time, any little motion. If the user scrolled up on the screen a little bit, it would call this again. It would happen so many times, you'd make a thousand API calls and crash the servers. That would not be a good thing. When you say comma and then you put these brackets here, then what you're telling the system is only make this call, so only run this code here, one time when the component loads up. And so that's the way that we're going to structure this.
AuthLoadingScreen.tsx
useEffect(() => { checkLogin(); }, []);
So, let's just hit save, make sure we don't have any errors. There's nothing really to test yet, because we need to add this to the router and so that's what we're going to do in the next guide. The goal of this guide was to kind of introduce you to the concept of how the secure store works and how you can call that. And then in one of the upcoming guides, you're going to see how we can actually store this secure token in whenever the user has successfully logged in.