Learn MERN by Building a Subscription App - Part 2

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
now that we got the server side up and running what we want to do is we want to actually utilize the routes that we created inside of our application so when we click sign up we should make that request that slash sign up route if we click login we should make a request that slash login route so let's just go ahead and do that right now so in order to do that what we're going to do is just close everything in here and we're gonna go to our client so we're gonna go to our client specifically we're gonna go to our modal.tsx and remember our modal.tsx is the thing that we're going to be utilizing in order to in order to sign in or log out so what we can do here because this modal is handling both logging in and signing up is we can actually pass in a prop calling is sign up flow and this could be a boolean value so if it's signing up then what we want to do is what we want to call the slash sign up route however if it's logged in then what we want to do is we want to call the login route so let's go here let's take out that prop and now what we can do is go to our app.tsx let's go to our hero and then in here we can say is sign up for this this is sign up so we can say true because we also could utilize the text but whatever we'll use this too and we'll say false for this all right cool so now what we can do is we can go to our modal and inside of our modal what we want to do is when we click this button over here we want to make that http request so let's add an on click here and this click is going to call a function called handle click so let's go here and let's say const handle click it's going to be an arrow function and then over here well what we want to do is we want to check well is it sign up or is it a login so you can say if is sign up flow is true then what we want to do is we want to make a http request to uh slash sign up now in order to make http requests let's install a library called axios so we're going to go here go to our clients we're gonna do npm install axios this is a very popular library in order to make http requests so then what we can do is we can get axios from axios once it installs there we go and then over here what we can do is we can do axios dot and then we can do axios dot post and then remember the request is sign in or sign up rather so we can go here you can say that this is the this is the url for the request that we want to make now of course what we want to do is we want to also pass in the email and the password now right now we're not really storing the email and the password that we get from the input anywhere so what we can do to fix that issue is have a bunch of use state hooks over here so we can do two-way binding for this so we can say email and then set email and then over here we can say password we can say set password and then over here what we can do is on the form control what we can very simply do is say that the value of this is the email and we can say when we change this we want to call a function so on change we want to call a function where we get the event handler and we want to set the email to e.target.value this is basic um event handling and react i do expect you to know this even if you don't come from a react background if you come from view or angular this is kind of similar to like the the uh the the v bind syntax so this is a very common syntax so let's see what's going on here it seems to be yelling okay okay the reason for that is over here we should set this to an empty string initially all right cool now let's go over here let's uh go to here let's just paste that in there instead here we're gonna say set password and we're gonna say password save that and so what we're going to do is we're going to make this request and we're going to give them the email and the password now the password can be completely invalid the email can be completely invalid it'll be handled in the back end all right so that's the very first thing that we're going to do is we're going to go ahead and make this request however if this is a login request what we can do is have an else statement and then in here we can have slash login instead okay awesome so what we're going to do eventually is we're going to get back some data from this so what we can do here is we can say let data we're going to say let data over here and for now we're just going to keep this with the any type and then over here what we're going to do is we're going to get back some data so let's actually just look at exactly what we get back so we can just say something like response is equal to a weight so this is going to be asynchronous so let's also async this and then over here let's do another response is equal to away so let's take a look at what we get back so let's try to sign up and let's console.log the response all right cool so i'm going to go ahead i'm going to inspect this console i'm going to go to sign up i'm gonna try to sign up with these credentials whatever so sign up and if i were to sign up seems like nothing occurs let me quickly refresh sometimes you might have to refresh you sign up okay so this was an expected error so right now what we're getting is we're getting a course error so this is a cross origin i forget forget what the rs stands for but essentially what we can do to kind of bypass this is we need to go into our server so we need to go to our server and then inside of our server what we need to do is we need to go to our index.ts and inside of our index.ts we need to configure that this client this one over here is allowed to make requests to the server that's the only issue this is the cores the the very common cores issue now in order to do this what we need to do is to install a particular package that allows us to kind of configure this so what we're going to do is we're going to of course open up our terminal as per usual and then we are going to install the cores package so let's move out of our client directory let's go to our server and we're going to do npm install cores now right now what we're going to do is we're going to go over here we're going to say course from course and now to say i guess we also need the types as well so let's do that as well say at types slash course dash dash save dev all right so now that we got that so now what we can do is we can say that hey we can say that well we want our client to be able to get access to the server in order to do this what we can do is right below the express.json we can add app.use and then we can say course and this is basically saying that whatever client it is that we want can connect to the server probably not the best thing we can actually it might be better to actually specify exactly what client is allowed to have access to our server but you know for the sake of this application it will just keep it as is all right so let's make this request again and now we actually get back our data so you can see here we get back data so now we're trying to sign up and if i were to go over here you can see i get back this token i get back this user i get zero errors now let's try to sign up again actually and now we get back this data but this time i get null for the data and then i get errors i get emails already in use okay cool so that's awesome so this seems like it's working so what we can do is we're getting back data and then over here we have this other thing called data so what we can do is we can actually extract out we can extract out from our mongodb so instead of just getting the response you can just get back the data you can just say something like we can recall this something like sign up data and then over here what we can do is we can say that so over here we can do that and then over here we can do the exact same thing for the login because we're going to get pretty much the exact same response so we're going to say log in data all right cool so i hope that makes sense so now what we want to do is we want to get this data of course and put it inside of this variable so now what we're going to say is we're going to say data is equal to sign up data so sign up data then over here data is equal to login data okay so now that we have this data we've hit these if blocks we either got error or we got the actual data in here now what we want to do is we want to check if we got any errors if we got any errors we want to throw up an error and this should be login data here or data is equal to this okay so the first thing that we want to do is remember how our data is going to be looking it's going to have this data property and it's going to have an errors so we're going to check if we have any errors if we have errors and we're just going to uh display an error onto our screen so in order to do this what we're going to say is if data dot errors dot length and what we're going to do is we're very simply just going to get the very first uh element the very first element inside of our array and we're going to display the message for that error so what we can do here is we can actually have another piece of state called show error we can over here say or maybe here we can call this error just error simply error beginning over here call this set error maybe even to be more descriptive you can say set error message over here we can say error message and we can say that this is equal to use state and an empty string all right so now why is it yelling at me so now what we can do is we can set error message to data dot errors again we get the very first element and we get the message of this so now what we can do is all the way at the bottom maybe right over here we can say okay well if error message is truthy then what we want to do is we want to let's go over here let's create another component here so we're going to say const error message is going to be equal to styled dot let's do a p tag here and let's import styled from styled components and over here we're just let's just give it a color of red all right so we what we want to do here is we want to display this error saying whatever the error message is okay cool so let's actually give this a quick go again let's give it a quick refresh let's try to sign up sign up with the same credentials we get this wow that is hideous okay but we're getting some some some actual real valid errors which is good uh let's just fix the look of this a little bit uh maybe if we put this in the body let's put it right here okay you know what that looks that looks good enough for me email already in use you guys get the point uh if i were to let's say i were to try to sign up and i'm trying to sign up with like an invalid email invalid email we get the email is invalid let's say the email is valid and now i'm trying to sign up with the invalid password i can go here i get the password isn't valid if i try to log in i guess this is the actual credentials let's try to log in with like invalid credentials you can see here invalid credentials okay cool so that's awesome so now what we're doing is we're error handling and we're also getting back the token so let's actually talk about how we're gonna deal with that token but i need a quick break before i do this so let's just do that in the next section whenever we successfully log in or sign up what we probably want to do is we want to get that token and then store it somewhere inside of our browser and then what we want to do is we want to redirect them to whatever page we want to redirect them to in this case we want to redirect them to the articles page so let's actually begin with actually getting that token and storing it inside of our client now our browser itself has multiple different ways that it can persistently store things inside of it if you were to open your uh you know google chrome extensions over here and you were to go to your application you can see that there's multiple different ways we can actually store data that is going to persist we can have cookies we can have you know session storage or local storage for this we're just going to simply store our token inside of local storage so what i'm going to do here i'm going to completely get rid of this token get rid of this token get rid of this what i'm going to do is we're going to store it over here as a key value pair so let's go ahead and do that right now so once we successfully have gone through this step then what we're going to do is let's go to handle click and let's go after this else block so after we go here what we want to do is we want to do a local storage dot set item and we want to set the token in there so we can say token is the key and then the value is going to be data dot data dot token very simple all right so let's just try to log in again let's just do a quick refresh let's try to log in with these credentials and we should see our token in here and now if you were to refresh our token should still be in there because this is persistent storage inside of our uh inside of our browser if we cleared the cache or whatever then it would be removed but for now it's going to be persistent okay awesome so now we were able to store this token inside of our browser next step is to navigate the user to the articles page so right now what we're doing is we simply just have one page so what we need to do is utilize react router dom to create multiple pages inside of our application so let's go ahead and do this so what we're going to do is we're going to move into our client and we're going to install react router dom react router dom so we're going to go ahead and install that tick tock let's just wait a little bit until it is done installing yeah okay awesome it's done installing so now what we want to do is well of course we want to set up react. i do expect you to know what this is this is just a way that we can set up pages and routing inside of our application let's get rid of this stuff that we don't use and then honestly it's also get rid of the app.css we don't use that as well then in here what we're going to do is we're going to import a few things from react router dom so the first thing that we're going to do is we're going to import browser router we're going to import routes so we're going to import routes and then we're also going to import route so browser router is the thing that we need to wrap our whole application in in order to in order to utilize the react router dom library so what we can do here is we can grab this browser router and just wrap it inside of our whole application and then over here what we want to do inside of here what we want to do is specify all of the different routes we're going to specify them inside of this routes component that we get from react router dawn and so in here we're going to specify a route so a route we're going to simply say that the path of an empty string which is going to be the landing page we're going to give it the element so we're going to give it the element of we'll call it landing page this is an actual page component and so now what we can do is very simply let's go to our source let's create a new pages directory and then inside of that let's create a landing page dot tsx all right very cool so in here what we can very simply do is just create const landing page is equal to an arrow function and we're very simply just going to return the hero component so this hero component because our landing page only contains the hero component so let's just go ahead and let's see if we can auto import that in and we can and then let's just do an export default of the landing page so the reason why we're only returning the hero component and not the nav as well as the hero is because we want the nav to appear in every single page so it's actually living outside of the routes sorry this should be routes not route so the routes component which is going to define all of our pages okay so now let's go here and let's import the landing page and get rid of the hero we don't need that anymore and if we were to save this and refresh everything should be still exactly the same but now what we can do is we can actually utilize react router dom to uh to move our user into a different page so what we can do here is go to our modal let's go to our modal and then from react router dom let me just clean up my mouse because it's just struggling to move this stupid magic mouse what we can do is we can import something from react router dom and we're going to import use navigate and so this is a very important hook that's going to allow us to navigate between our application so in here we can say const navigate and that's going to be equal to use navigate we're going to go ahead and invoke it now what we can do is we can actually utilize this function over here at the very bottom and then simply say navigate and then we can navigate to the slash articles page so the slash articles page so what we want to also do here is return so we want to return this so essentially if we get an error we don't want to invoke this however if we bypass this if statement then we want to put the uh put the uh the token in local storage and then navigate to the slash articles page so let's go ahead and save that let's refresh let's give this a quick go again let's just do a quick refresh here let's log in with these credentials and there we go awesome so and you can see here that the nav is also present in this page as well all right cool now right now this page doesn't really exist um and that's that's this is the main reason why we're not seeing anything but of course right now we don't have any plans so we should see uh we should see kind of saying an error saying that hey you don't have any plans go to the plans page all right cool very cool also our navigation isn't working so when i click uh home it's not taking me back to home so let's quickly fix that right now now that we have a react router dog so to fix this let's go to our nav and here what we can do is from reactor order dom we can import this thing called link and this is a very important component that we can utilize so inside of link inside of the nav link we can have this link over here and we can say that this is going to slash this slash over here so this is a landing page now i actually wonder let me just do a quick inspect i wonder if we have an anchor tag inside of an anchor tag in this case and that's exactly the case so maybe what we can do instead here is just copy the class copy this class uh uh put that in there and just remove this link right here so now we just have one anchor tag all right cool and it's of course class name there we go all right so now if i were to click back here we go go back home okay cool so this is this is awesome this is this is really cool right now when we log in we get redirected to the articles page and of course we have nothing in here because we haven't defined anything inside of the articles page however right now i want to focus on something else specifically i want to focus in on the nav bar so let's actually take a quick look at the navbar i'm going to quickly zoom in here so right now the navbar only has one tab however when i'm logged in i actually i'm going to expect that we have two tabs the home tab as well as a log out tab that is going to give me the ability to log out and of course i only want to show the log out tab when a user is logged in so we need a way to identify that a user is logged in inside of our react application and then if they are logged in we can show different ui elements so how do we identify if a user is logged in or not well if you remember let's open up our dev tools as soon as a user logs in or signs up what we do is be inside of local storage we store their json web token inside of a key called token so you might be thinking okay it might be a good idea to go to local storage get the value of the the token property and then say okay well if there's something in here then just show the log out tab however if there is nothing in there well don't show it because that means they're logged out okay cool so this seems like a good approach and let's actually just quickly implement it right now so right over here what we're going to say is local storage so localstorage.getitem so we're going to get the value of the token and if there's actually something in there then what we want to do is we want to render this nav item so this nav item we're going to call this logout okay however if there's nothing in there then that means we're logged out so we don't want to show the log out nav tab so you can see here that this works perfectly fine that's awesome so this seems to be working we are authenticated and we should see this and if we were to remove this this token and we were to refresh okay awesome so now it's not there that is terrific okay you probably get the problem with this approach this approach is very very problematic why is that well anybody has access to the chrome dev tools anybody can go to their local storage add a key called token and put in some random gibberish and even though this is not a valid json web token now if they were to refresh their page now they have access to this logout tab or any other ui elements that you only want authenticated users to see so this approach is definitely not a good one and we are not going to be taking this approach to identify our users so what are we going to do instead well we're going to utilize our back end where is my canva right here we're going to utilize our back end to do this so this is going to be the most secure because the client any user can manipulate the client in any way but they cannot manipulate our server our server is completely isolated from the client and so what we're going to do is we're going to do a majority of the authentication steps right over here the validation steps right over here inside of our server so what are we going to do well our client as soon as we open this page as soon as we open our website we're going to go to our local storage and grab the token if it exists if it exists we're going to go ahead and make a request to the server with this token we're going to make a request to the server with this token the server is going to verify the token remember with json web token right over here we need to verify the token and then it's going to take once it verifies it it's going to take the payload that we applied over here which is the email it's going to find whatever user has that email and it's going to send back those credentials and this ensures that we are really logged in and this is the approach that we are going to take but before we do that we first have to talk about exactly how we're going to be sending this token from the client to the server you might be thinking that well this is kind of a stupid question we've been sending data from the client to the server by utilizing if i go all the way over here by utilizing the request body well for the token itself this isn't a really good idea the request body should be reserved for data that is specific to that route so this token isn't really specific to that particular route so how are we going to send this instead well there's multiple ways we can send data from the client to the server it doesn't just have to be the body the more the most common way of sending the token from the client to the server is by using the request header so if you actually go all the way over here we can see here that we have this headers option and there's actually a key value pair so we can have a key of authorization and then a value of our token and the common convention for sending our token is going to be bearer space and then our token this doesn't really do anything special it's just a very common convention of sending tokens from client to servers and that's exactly what we're going to be doing and so for every single route that we hit we're going to be sending this token inside of our request header so for example we're going to have a me route that is going to identify who we are and this is going to be a protected route you can only hit this route if you are logged in if you're not logged in you should not be able to hit this route so what this route is going to do is it's going to take the token it's going to take this token it's going to verify it so remember the tokens they have to be verified with this portion right over here then it's going to extract the payload from this token it's going to go ahead and maybe make a fetch for that particular user with that email and then it's going to return that back to the client so every single every single authenticator route is going to go through these same steps so for example we might have the articles and this is also going to be an authenticated route and then over here we might have you know slash sessions to create a stripe session and this also is going to be authenticated route so you have to be logged in to hit this so in order to accomplish this what we would have to do if you want to hit the slash articles and get the articles what you would have to do is inside of this route you would have to again extract the token verify it extract the payload fetch the user and then you can perform whatever logic it is that you want so the only issue with what we're doing right now is we're that we're really replicating our code throughout every single authenticated route wouldn't it be great if we can somehow identify which routes are authenticated and then we can run some sort of function that does the verification step and the extraction step well there actually is so for all of our authenticated routes what we can do is we can define something called a middleware and this middleware is going to essentially intercept the request and it's going to perform some logic and then if everything is all fine and dandy is going to take that request and then send it to whatever route that we want to send it to so for example if we want to go to the slash articles what we can do is we can send that request it's going to first go to this check authentication middleware and this middleware is going to again extract the token verify it and then it's going to get this user and is then going to say okay well everything is fine this person is logged in let's relay that request to the slash articles route however if this person is not if this person is not authenticated what it can do is they can say no i'm not going to relay this i'm going to go ahead and throw an error to the client telling the client that hey this person is not authenticated so essentially if we ever actually end up just hitting this route we know we're authenticated because we have this middleware so that's exactly what we're going to be implementing inside of this section of the video so let's go ahead i hope that makes it clear to you guys authentication is kind of a notoriously difficult thing to implement but hopefully these diagrams make everything clear all right so where were we let's go to our code we have so many tabs open let's get rid of this gibberish and right now we're going to very simply work with the client or for the with the server for now so let's go here let's go to our server so we're going to go to the auth because this is at the end of the day it is going to be an auth route and let's create that me route so we're going to create that mi route so let's go here sorry i had to go log back into my notes so we're going to go over here we're going to say router dot get this is going to be a get request we're going to say slash me and then we're going to have over here we're going to do async rec res now remember over here what we want to do so let's just go here let's just do a red so let's send me route and let's go over here let's create a new request let's save this save that and then let's add a request here and then over here we can save that and go here we can just say me just to see that this works okay so we get the mirror so this works completely fine okay so remember what we want to do is we want to have a middleware in here so we want to have a check authentication middleware we only want to run this if we're actually logged in so let's actually just create the middleware and then we'll create the logic a little bit later for that middleware so inside of the source directory what we can create is a new directory called middleware so we can create a middleware directory and then in here i'm going to have a check off dot ts file so i'm going to have this check auth.ts file and then right in here what we're going to do is we're going to create the logic for uh for uh you know verifying our token so let's just get right into that right now so the first thing that we want to do is we want to create a function and this function is going to act very similar to the callback functions that we have over here so what we're going to do is we're going to do export const and we're going to say check off and this check off middleware is going to be asynchronous and it's going to take in three different things it's going to take in the uh so it's going to take in the request so remember the client over here is going to give it the request to the author middleware and then it's also going to take the response so remember the response at the middleware might be able to just straight out to respond to the client and then it's going to take in another parameter called the next parameter okay so let me just quickly define what's happening here so the request is the incoming request from the client the response is just going to give us the ability to respond from the client from the middleware the next thing is essentially saying that okay everything here is fine i'm going to invoke this next function which means go to the route handler or the next middleware inside of this route so saying just move on from this and go to the next chain which could be another middleware or the actual route that we want to hit right now we're getting issues from typescript because typescript has no idea what rec res and next is so in order to fix this we can just import the types from express and let me just get rid of this we can import over here from express we can import the request the response as well as the next function and we can define the types here so we can do request response and the next function all right cool so let's go ahead and save that and there we go so now what we want to do is let's just very simply console.log hello i am a middleware i know you guys can't see this and it seems like everything is capitalized whatever and then we're going to go ahead and invoke the next function so what i want to do is i want to utilize this middleware this check auth middleware inside of this route only in order to do this what we need to do is import that middleware so let's do import and honestly you know what let's just say check off and have it auto import and then what we can do here is in between where is it in between the path and the callback function which is our route we can specify the check off middleware and so what's going to happen is it's going to go in here first and then it's going to go right over here so i hope that makes a little bit more sense now before we actually end up doing this what we need to do is we need to go ahead and just save this up so now what we can do is let's just go ahead and let's run this and it fails why fails it fails let's run this again okay there we go so it hits the mirror out and you can see here that it's inside of the middleware now what we can do is we can actually say that no we don't want to hit this next what we want to do instead is you know you're not authenticated so we're just going to say return or we can say res dot send you know something like not authenticated so now it's not even going to hit that meme route instead what it's going to do is if i were to send this off you can see not authenticated all right so that is middleware in a nutshell so now what we want to do of course if you is we want to identify our user so let's go ahead and well do that right now so inside of the middleware we're actually going to want to create the real logic for our middleware so the first thing that i want to do is i want to get the token and i'm going to get the token from the request header and this is going to be authorization so so this is going to be the key we're going to call this authorization so the first thing that we're going to do is we're going to go ahead and just console.log this token and maybe even just return it so we'll do a res.send token just to see if everything works so let's go into our clients let's grab a real token so let's just log in grab that real token copy that token and then in here we are going to have header we're going to say authorization we're going to say bearer and then we're going to say this token okay cool so you can see here that now this is actually being sent to our middleware awesome cool so now what we want to do is we want to of course extract the token so we want to extract this token from um uh from uh this this bearer string so very simply what we can say is you know if the token doesn't exist what we want to do is we want to just say that you're not authenticated so we're going to very simply say return res.status this time we're going to have an actual status we're going to say 403 meaning that this is forbidden and we're going to send back some data saying that you know the error is your unauthorized unauthorized so let's just give this a quick go again let's just get rid of this and let's give this a request you can see here we get a 403 unauthorized now let's go back over here let's add that token again and if you were to send this off again everything is fine so there's no token you're unauthorized and now what we want to do is we want to simply split the token so let's just do a let token here and we can say let token and then this is going to be equal to whatever the token is dot split we want to split it between the space and we're going to say token all that token and then what we want to do is we want to get to the uh the second element so what this is going to do very simply is just split these into two different arrays we're going to have bearer and one element this in the other element and we're going to get that so that just allows us to get the token itself all right cool so now what we want to do is of course verify this token so in order to do this we're gonna utilize the jwt package so from json web token and then in here what we're going to say is well jwt dot verify and what this is going to do is it's going to actually throw an error if our token is invalid if our token is valid however it's just going to extract the payload and give it to us so what we can do is actually put this in a try catch block and we can do jwt dot verify and then over here what we can do is jwt dot verify and this is going to be asynchronous so we can simply say const user because we get back the payload and we can say await and then in here what we can say is well you first want to give it to the token and then we want to give it the secret that only our server knows and remember this is inside of our process dot n dot uh jwt secret so it's going to verify that our token is actually correct based on the secret that we have inside of our server so i'm going to say as string okay cool so that's pretty much all that we need now if we end up actually getting our user so what i want to do is i want to take the request i want to set a property on the request i want to say that the request.user is equal to the user.email so now if i were to go to this auth route over here what i can do is simply say rec.user and that will be the email of that particular user i won't be have access to that in here because i wouldn't have hit the middleware but over here i can actually get the email and maybe do something with it because again i am authenticated now the issue is in typescript this would be complete or in javascript this would be completely fine but because we're doing typescript it's just a little bit more tricky so if i were to hover over this it says that user is not does not exist on type uh this right over here so basically what it's saying is this user property doesn't exist in the request type that we defined so what we want to do is we want to just say that this is completely fine and we want to add this user inside of the res the the the request type so in order to do this we're just gonna have to do a little bit of trickery when it comes to typescript so this is just kind of the annoying part of typescript sometimes but hey it is what it is so in here what we're going to do is very simply we're going to add an at types directory and then in here we're going to have an express directory and we're going to have an index.ts file in here so right in here or actually we're going to call this not index.ts we're going to call this index dot d because here we're defining some type definition so index dot d dot ts and over here very simply what we're gonna say is declare namespace and we're gonna say express and over here we're going to do export interface and then we're going to say request so this is the request and we're going to say that we have a user in there a user property that has the string all right so i hope that's clear essentially what we're doing is we're just getting the uh the request type from express and we're adding this user property that is a string and we're going to utilize this to uh essentially just create the um essentially just create the uh the the email okay cool so now what we need to do is to go to our ts config file so inside of our ts config file what we need to do is define is defined let's go over here we need to define type roots and then here we're going to say at types so at types and then over here we're going to specify the route to that so we're going to say node modules slash act types and so this is this is essentially going to say that we want to add this to the root types inside of our node modules and now if we were to go here we still get this error uh what is that error so email okay yeah so so the the issue here so now what we can do is we can actually change this to a string that's completely fine but now we're running into a separate issue and this issue is hey this could be string or type uh you know json so for this we can just simply say that this 100 will be a string and this doesn't actually seem to be working let me just quickly check my notes as to how i did this so let's go here and over here okay so instead here what we can say is over here we can say that hey we get back so what we do is we get back something called email that is a string and that just fixes that issue all right cool okay awesome so now that we have that try catch so now what we did is we actually set the rec.user we have the email in there you can also call this email if you want but whatever that's completely up to you and then once we do that we want to execute the next function now if we ever hit this catch block that means that the token has not been verified so what we can do very simply is just return this so we can return the exact same thing all right and that's pretty much it we don't even need this part so now even if we send let's let's send some gibberish so let's go ahead here and let's just send let's send an invalid token so let's send whatever this is at this point we're unauthenticated however if we sent a real token then we are authenticated and we actually hit that route and now what we can do again is go here and we can access the rec.user and the rect.user send this off again wait why did did it fail or is it still reloading let's see yeah i think it was just reloading let's send this off now you can see we actually get that user's email so now what we can do in here is very simply just go and just say sim just say const user is equal to await user dot find so find one and we want the email to be whatever is inside the rec.user and then over here what we can say is return res.json we can say that sorry about that let me just you can say this so we can say errors of nothing and then the data is gonna be um it's gonna be a user and we're gonna have an email of user dot email maybe we also want to get get their id so we can say id is user dot underscore id all right cool so that's pretty much it now why is this yelling at me over here i cannot find name errors okay yeah just typescript taking a long time to understand what i want so now what we can do is if i were to make this request and wait a million years what is going on maybe this time it's actually failing uh okay let's see why that is let's open up our terminal again close this off so cannot set headers after they are sent to the client what is going on here so hmm that is a little confusing i don't really know what cannot set headers after they are sent to the client well where are we setting the header here uh okay okay i figured out what was wrong i have this i'm sending data then i'm sending more data i can't do that so let's get rid of that and now what we can do is if we were to make this request again and wait a million years you can see that we actually get back the correct data and we figure out exactly who we are all right so that's pretty much it for the me route we learned quite a bit about middleware we also added this uh so that now we can authenticate all of our routes so now what we need to do is we need to go back to the client and then handle this data globally inside of our application now that we set up the me route let's go ahead and make a request from the client as soon as this website is rendered and once we actually get that data what we want to do is we want to store it globally inside of our client therefore any component that wants access to it we can quickly give access to so for example the navbar or any other components within our application now in order to store our state globally we can use multiple different approaches for example we can use redux which is i think a bit of an overkill it's a little bit too complicated we can use use reducer which i think also is a little bit overkill instead what we're going to utilize is use context which i think is probably the simplest way to store global state in react and it's actually the best way to do it for our uh for our uh problem at the moment so let's go ahead and use use context in order to make that http request get the data and then store it in the global state of course if we are logged in all right so the first thing that we want to do here is let's go to our source directory and let's create a context directory and then inside of here an index.ts file and then here is where we're going to create our contacts so remember the contacts is just a place where we're going to store our state so what we can do here is very simply imports uh something from react and that something is create context so create context and before we actually go ahead and create the context let's let's think about how that context is going to look how that state is going to look and the best way to do this is by just creating an interface a typescript interface that's going to define how our data which which is going to be our context is going to look so what i think is best is to have three different properties data error and loading so if if so remember the context is going to be making a request this is going to take some period of time and so this is why i think we need loading and this is going to be a boolean value so either true or false this is indicative of hey something is loading now once we get back a response we can actually set this loading to be false and then if you get errors what we can do here is we can well display those errors so this those errors we can maybe give them a type of string so they're going to be string however if we get data then we don't have any errors so we don't want to put any string as an error so we can say string or no now the same case goes with data so data what we're going to want to get back is an id that's a string we're also going to get back an email that's a string however if we get error and not data then what we want to do is we want to say well data is null for example if we're not logged in well data at this point is going to be null all right cool so that is how we are going to define our data so let's go ahead and let's create our user context so we're going to say user context and then that's going to be equal to create context so create context and so right here we're going to go ahead and invoke this but what i want to first say is that it's yelling at us for a very particular purpose we have to define we have to define the context initial values or default values before we actually create them so what we know is okay well what we want is some sort of state that looks like this but what we also want is the ability to update this state and actually this state is going to be living inside of a u's state hook and so what we want is we that we want this context to have the state of this as well as the ability to update it so what we can do here is pass in an array and then inside of the array we can just have this initial state so initially we're just going to assume that everything is loading so initially we can simply say that data is null we can say that loading is is uh true and then we can also say that error is no so that's initially what we get here and then what we can also get as a second parameter and this should be inside of an object in this array as a second parameter what we want is just an empty function so just an empty function this is going to be the function that is going to update our state we can actually define that inside of the type right over here so we can have these types right in here so we can say that we're going to have a user and then we're also gonna have a react dot dispatch we're gonna have react dot dispatch and then over here we're gonna have a react dot set state action and then here we can have user and you don't really i mean this might be a little bit confusing but essentially what this is is this is the type of a use state hook that has uh that has this particular data all right so and this should be capital set there we go okay cool so now that we created the context let's create the provider so we're going to say const user provider and then the provider is going to be equal to and then over here we're going to have we're going to pass in any children so these are the uh children um these are the children react components for now we'll just say that they're any we're gonna go ahead and in here what we're going to do is we're going to create that use state so we can have that initial state that we created so in here we're going to say const and then we're going to say user and then over here we're going to say set user and then over here we're going to say use state and we're going to have the type of user in here and we're going to have the initial value that we had over here okay let's just save that let's save this we're gonna have this initial value right in here okay and just to let you know that i didn't kind of come up with this state this type right out of midair what i did was i just hovered over this and i hovered over this and i just copied this type right over here so you can do the same if you want to you probably already did it so over here this is the uh the use state so this is the current state of our application and so now what we want to do is we want to fetch so you want to fetch using that me query but before we do that we have to ensure that our token is inside of our header so let's go ahead over here and we can say const token and we can say cons token is equal to local storage dot get item and we can get our token and then what we could do is we could actually instead of passing it in manually for every single axios call that we do what we can do is actually add this token into every single request by having just one default configuration so by doing that what we can do is we can do import axios from axios and then right in here we can simply do axios dot defaults and then dot headers dot headers and then dot common and then we do our square backwards and this is going to be the key authorization we're going to say that this is equal to template literals bearer and then our token that we got from local storage so our token that we got from local storage okay cool so what this is going to do is it's going to set all of our uh it's going to set all of our um uh it's going to set all of the headers our request headers to have this now we only want to do this if we actually get a token so we can simply say something like if token and then we can do that all right cool awesome awesome so now let's go ahead and we're going to actually go up and make that request so let's create a function called fetch user and this function is going to well fetch our user it's going to make that async request so in here what we're going to do is we're going to get the data so we're going to over here get the data we're going to do an await axios dot get and then over here we're going to do http colon slash slash local host and then we're going to do colon 880 slash off slash me it's going to get whatever user that we are currently in and that's because we're gonna of course add the header inside of the uh um instead of the request that's how we're going to identify who we are and then what we're gonna do is well once we get our data back what we're going to do is well we're going to check if we actually get our data back so if data.data and actually let's just make this request just so we can see how this looks so we're going to say here console.log data and let's just uh invoke this so just gonna go here here and invoke this now in order to actually set up this context inside of our application what we need to do at the very bottom is we need to export out the user contacts as well as the user provider if i'm going a little bit too fast here i kind of do apologize i i'm hoping that you know what the context is before you're kind of watching this or if or if this is a little bit clearer to you guys so let's go here we're going to say the user provider and then we're going to go ahead and export it out now in order to actually utilize it what we need to do is we need to go to the app.tsx inside of our um inside of our application so the app.dsx or even actually maybe the index.tsx inside of our application because this is the root of our application so let's go here and then in here we're going to have to wrap our app with the user provider so we can very simply maybe we can even auto import it so we can say here user provider we can auto import that in and we can wrap our application with that user provider all right so let's go ahead and save this it seems as though everything is fine oh yeah so we're also missing we have to return some jsx for sure so let's go over here and in here what we're going to do is we're going to very simply return the user contacts dot provider then over here we're going to set the value of uh this right here so user and set user we're going to close this off and then in here we're gonna pass in some children all right cool and so now it seems completely happy okay cool so let's actually just invoke this inside of a use effect instead of just having it there so i have a use effect in here we're just going to invoke this once so we're going to go ahead and call fetch user all right cool so now if i were to try this we were to console.log you can see here that we get this data back so we get no errors and we get the actual user that we want so this is this is me so what i can say here is inside of the inside of the inside of the fetch user what i can simply say at this point is well if the data exists so i can say if data dot data and data dot data dot user so here i'm saying if so this whole object is called data so we can say if data maybe to make it clear maybe we can recall this response so we can say if response.data exists and if response.data.user exists because remember this could be null then what we want to do is we want to set our uh set our state to be a little bit different so in here let's get rid of this console.log so in here what we want to do is we want to set user and we want to set the user to have the data of we're going to have id of response dot data dot user dot id and then we're also going to have the email of response.data.user.email all right so that's the data portion of it typescript is yelling at us because well loading at this point is going to be false so loading is false and then we're going to say here error is no error is null now at this point let's also have an else if block and we're going to say if response dot data and response dot data dot error errors so it's going to be errors array and dot length so we can go ahead over here and do the exact same thing however this time what we want to do is we're gonna go and we're gonna take this we're gonna go here slash errors dot zero dot message we're just gonna get the first message and set that as the thing and data at this point is gonna be null all right cool so that pretty much sums that up so now in here what we are going to do is inside of the use effect we're actually just going to make this function call so we're going to make this function call i'm really going to make this function call if there is a token inside of our application so we're going to say if token if there's no token there's really no point of trying to fetch the users we're going to go ahead and fetch this however if there isn't well we're locked out at this point so might as well just double check and just set the user to the logged out state so data is null we're not loading so loading is false and then error is null so this is probably one of the more confusing parts of this application but i hope it's relatively clear at this point maybe take a quick break and read it over if you're confused so now that we did this what we can do is we can actually utilize this context in order to um you know make changes in our application let's actually do that in the next section let's now utilize that contacts that we set inside of our nav so essentially if we have data what we want to do is that means we're logged in and we want to add another nav item saying log out however if we don't have that item then we just want to keep it as is so in order to access the data from the context what we're going to need is the use contacts hook from react so we're going to need use context from react and we're also going to need that user context to define exactly what context we want to utilize so we can simply say here const whatever is equal to and then we're going to say here use context so use context and then we can go ahead here and say user context so we can just auto uh import that in now remember what this is going to do is it's going to return an array so what we can do is we can say that we want to extract the elements from the array the first element is the user or or maybe the data themselves or we can maybe call this i don't know we'll call this user or or maybe state and then over here the second one is the set state so over here is the set state so this is a function that is going to be utilized to change the state and this we're probably not going to utilize the set state actually we might when we log out so actually we'll keep that in there and so let's just go ahead and just console.log the state at the moment just so we can see exactly what we get back so let's and let's also say that this is inside of the nav because i'm not sure if we have any other console.logs just lurking around so we're going to refresh and you can see here that initially the state is loading and then once we get back our data we actually get back some real data so very simply all we really have to do is in here we can just say well if we actually get back state dot data meaning we actually get back some data which means that we have the user we can simply just render so we can actually render this element so we can say here over here we shouldn't use curly braces we should use this we can just render this element and over here we can very just simply say log out and i don't want this to be a link we can actually make this a nav link instead we can get rid of this and we can just simply say log out so log out all right cool so now you can see that we are logged out now if i were to go or i actually i'm logged in which means i have this logout tab so now if i were to go over here to my application and as you can see here we have a token and we have you know an actual json web token if i were to get rid of this and put any sort of gibberish and refresh well now i'm actually not logged in so now we actually cannot manipulate the ui elements depending on whether we have something in the token or not it actually has to be a valid token that corresponds to our account so let's refresh that again now we're actually logged in all right cool and that might be really small for your screen but i'm hoping that you guys actually see this okay cool so one thing that i want to do is i want to just move this log out tab to be all the way uh to the to the right so that's actually kind of easy what we can do is we can use just a styled component for this we can say import styled from we can from styled components and what we can do here is we can say left nav container is equal to styled dot div and then in here we can just simply give this a margin left of auto all right so we can give it a margin left of auto and then what we can do here is very simply just get this container and we can just wrap it across the nav item so you can wrap that right here and now this should be all the way to the left all right cool so the last thing that we actually need to do is just to make this uh log out well functional so how are we going to do that well it's actually going to be really really easy so on click what we want to do is we want to change the state so we want to change the state to of the data to null and what we want to do is we want to maybe just navigate to any other particular page so what we can say here is handle logout you can create this function over here called const handle logout and then in here the first thing that we want to do is we want to set the state so that the data is now null so the data is now null we also want the loading to be false because we're not loading anything and then the error to be null because there is no error so that's the first bit then we want to remove that token from local storage so we're going to say localstorage.remove item we're going to remove that token and then what we want to do is if you're inside of any any page what we want to do is we want to navigate you to the home page so from react router dom in order to do this we can just take use navigate like we did before we can do const not the gate is equal to use navigate you can invoke that and we can say here na v gate navigate back to the home page and that's it that's all we have to do we don't need anything in the back end we just need to remove the token and we need to just move our application back to the home page that's all we have to do so right now you it might be really faint but i'm in slash articles if i were to log out now i go back to the home page and that's awesome okay cool so now what we want to do is we want to start actually working on the articles page so let's actually get into that in the next section let's now work on the articles page so when we go to slash articles we should see something now specifically what i want to work on is if we're not logged in we actually shouldn't have access to the articles page so what i want to do is i want to figure out if we're logged in or not if we are logged in we should have access to this page however we might not have access to specific articles based on our plan but if we're completely logged out we should just never enter this page so if we try to go to slash articles what i should do is just redirect us back to the home page so what we're going to do is we're going to create protected routes based on whether we are authenticated or not okay so in order to do this let's just first go to our pages directory and then in here we're going to create an articles.tsx file and this is just simply going to house our article page component so you can say const article and then this can be an arrow function and then this can return just for now just an empty div just saying articles and actually maybe we can actually use a container that we get from react bootstrap just so it can look a little bit better okay and let's go ahead and export default this so export default articles you can call this articles and now what we can do is you can go to the app.tsx so inside of the app.tsx what we can do wherever that is is inside of here we can create another path and this path is going to be slash articles and then this is going to take us to the articles page so we can say rt calls and we auto imported it so now when we uh log in we are redirected to this page right over here okay cool but of course if we're not logged in and where's the log out option actually i'm a little surprised here okay so we actually have another issue here when we log in we actually don't see that log out tab and the reason for this is we have to actually add some logic inside of the modal so let's go i guess we're going kind of a segway here but let's just quickly fix that issue right now so what we're going to do is we're going to go to the modal in here and then we're going to add some logic inside of this modal so inside of this model what we want to do is when we log in we want to set the context so we want to set the context to the user that we are logged in as so let's actually go ahead and let's do that right now this is going to be relatively simple so let's go here we're going to say import and we're going to import use context from react now are we getting anything from react or svr so we can just very simply go here and just get use context all right so right in the handle click we're going to change a little bit of our logic so inside of the handle click what we also want to do is go over here and we want to get const we want to say state set state and then over here we're going to say that that is equal to the goose context and we're gonna call the user context all right cool so right in here so right here what we want to do is you also want to set the state so we can very simply say here set state and then we can say that the data is going to be equal to the id and then over here we can say that this is going to be data dot data dot user dot id and then here we're going to say email and then this is going to be data.data maybe maybe it'll be more clear if you can just call this response so response here response here response here response here response here and then here what we will say is response and then response and then here also response just so we can make it more clear we're getting the response.data.user.id response.data.user.email so that's the data and then for loading we'll set that to false and then for the error we have none so no okay and that's pretty much all that we need to do the other thing is uh if we ever hit this state we also want to set the axios header to have our token so we also want to do that as well so we can very simply say here axios dot defaults dot header dot common we're going to say here authorization and we're gonna say that that is equal to bearer and i think this should be headers bearer and then dollar sign curly brace and we're gonna say response dot data dot token remember because here we get the token back all right cool so why is this giving me an error so we're saying okay now it's fine all right so that that fixes that kind of issue if you were to log out now and try to log back in now we get everything up and running okay cool so now that we got that out of the way let's actually figure out how we can protect routes so in order to protect routes what i'm going to do is i'm going to create a protected routes component so in here we're going to create a new file we're going to call this routes i'm going to say this is a protected route dot tsx so protected route dot t s x and then inside of this protected route we're going to create a very simple component so let's go ahead and let's just do an export const we're going to say protected route and that is going to be equal to so that's going to be equal to a some some arrow function and then very simply what we're going to do is we're going to get the state from the user context so we're going to get the state from the user context user context and this state over here is just going to indicate whether we are logged in or not so we're going to say the first thing that we want to do is we want to check if the state is loading so if it is loading then what we want to do is just very simply for now just return some spinner because we could hit a point where we are loading so we want to just hit a spinner because if we're loading the data at this point is null and if we check if the data is null and just say that hey you're not protected well that might not be the case because we just might be loading at this point however if we actually have data so if we're not loading and we have data then what we want to return is something called outlet and i'll explain exactly what this is a little bit later but if that's not the case then what we want to do is we want to return another component called navigate so this is very similar to um this is very similar to uh the use navigate hook but it's a component that's just going to navigate to a particular page we can get this from react router dom so over here we can say that we want navigate so navigate now over here what we're saying is this is a component that is going to navigate to so it's going to be a component that's going to navigate to the slash space which is the landing page and that's all we have to do for our protected route so now in order to utilize this inside of our app.tsx all we have to do is simply import import protected routes just go ahead and import that protected route did that get imported come on get imported there we go so we're going to get a protected route and then we're going to wrap so what we're going to do is we're going to wrap uh what we're going to do is we're going to wrap this right here so this route that we want to protect with another route so we're going to say route and we're going to have and this is not going to be a self-closing one so we're going to have route and then over here we're going to wrap it inside and then we're going to have the exact same path so we're going to say path articles but this time the element is going to be equal to the protected route so protected route so we can go ahead and save that now we'll explain exactly what's going on here in a second but let's try to log out so now we're not logged in and let's go over here and let's go to slash articles and you can see that it's not letting us so you can see that we don't have access to slash articles so let's just quickly explain what's going on here so what we did was we created this thing so if we are loading we're just going to return a spinner and so very simply we can log in just to really see that so if i were to go over here and now at this point i am logged in i do have a token inside of my uh inside of my local storage and if i were to very quickly go to articles you'll see a you might have seen a very quick spinner and then it showed us our page so this is just a loading state now over here if we actually have data which means that we're logged in what we want to do is we want to return outlet an outlet is very simply a component that is going to return the child that is inside of that route so for example over here inside of app.tsx we're wrapping this route with another route and if this ultimately just simply returns outlet then it is going to utilize this route which is the child so it's basically saying that hey just utilize whatever child is inside here however however if um if we don't have any data which means we're not logged in we want to utilize this navigate component that we get from react router dom that's going to navigate our page to the slash so i think this this one makes a little bit more sense it was just the outlet that was a little confusing okay cool so i hope that makes sense and now we got to protected routes so now that we got protected routes well now what we want to do is this is where the actual action and the fun part gets in so now what we want to do is we want to start creating our plan and so we're going to need to interact with stripe to do this
Info
Channel: Laith Harb
Views: 1,717
Rating: undefined out of 5
Keywords:
Id: MHyvZ0jHO3A
Channel Id: undefined
Length: 85min 15sec (5115 seconds)
Published: Tue Nov 23 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.