React Login with Apollo Server, Context, JWT (Apollo Server Tutorial)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey there it's cooper codes in this video we are going to be creating a react login system using json web tokens and apollo client so in this tutorial we're going to be doing a lot of different things so it's going to be a bit of a longer video but it really is the full stack implementation of creating an authentication system even though it's a lot of stuff it should set you guys up for a bunch of success for whatever react projects you want to create that being said in this tutorial we're going to create an apollo client for our react front-end to use this is for things like actually using apollo code like use query use subscription um no subscriptions in this video though but just you know that's the client that would get used then we're going to create a navbar with login and log out functionality kind of like what you'd expect on a regular website and we're also going to create those login and register react components using material ui i chose material ui for this project but you can use any ui framework you want you'll see at the end of the day it's just you know a function attached to some button we'll get into that later though and we're going to want to use react router to handle links to the login and register pages and then create a react context that allows us to store json web tokens of users that have logged in registered so this video uses a backend that i created in another video that handles the user authentication side you know where do these json web tokens actually come from how do they get created that's all covered in this video here if you haven't already take a look at this video first and then come back to this video when you're done with it this step isn't necessary though if you have your own login system for example you already have some type of back end returning a json web token or something along those lines and you know you just want to learn more about react context or apollo client then keep watching there's still a bunch of value here even if you haven't gone through this video something i do in a lot of my videos is i show you the actual kind of system diagrams behind what code we're doing i do this in all of my videos because i feel like a lot of tutorials can get you stuck if you're just looking at someone creating code and so i do this to show you guys how you can break down a problem in a way that isn't just code because at the end of the day all these technologies all these languages they're just tools and understanding the overlying problems and being able to break down those problems yourself is a huge part of the learning process so let's take a look at registering users so we start with this apollo server that we created in that video i just mentioned and it contains a login user mutation and a register user mutation our react website is going to look something like this in the middle here it's going to have an email input and a password input and then it's going to want you to register this is just an example we probably have more inputs than this but when we press this register button a couple things are going to happen first thing you want to do is when you press register we want to run the register user mutation with the inputted data so we're going to try and register a user with the email of a certain email and the password of a certain password and we're going to run that register user then we're going to return the created user or the errors caused in the backend just some example errors could be that uh someone's already registered with a certain email and so our backend is going to handle those type of errors and give those errors to our front end when we get a created user from our backend we want to store that json web token in our local storage this token is important as it shows a user x whoever it is has logged in successfully a quick side note what is local storage local storage is something that is attached to our window so it actually has nothing to do with react specifically it has more to do with uh web api stuff as you can see here specifically to do with window and local storage allows us to set and get items locally from a user's local storage so for example this is setting the item my cat to tom we can do the exact same thing by setting the item token to our current json web token representing the user and local storage is surprisingly simple it's literally set item get item remove item and also i believe clearing all items it's one of my favorite ways to manage stuff like tokens where you just want a simple get set remove and it does all that stuff for us so we're going to be using local storage alongside our apollo client so let's also go over how to login users we're going to have a very similar looking react website except this time we have a login button when login gets pressed we want to run the login user mutation with the inputted data like i discussed before very similar thing login user gets ran with email and the password whatever inputs we decide to use and then we are going to return the validated user or the errors calls on the backend for example invalid email password etc when we get a successful login though it's going to give us a json web token that we want to store in our local storage so storing json web tokens with react for this video we will take advantage of react context so context is overpowered because it allows us to store things in our application that can be interacted with anywhere so this means that any component any page whatever we can use our current user data if we make that part of a react context for example so we can create login logout functions to handle the current user context shown here we're going to make something called an authorization context which means we'll have a context that can be used anywhere and i'll ex i'll show you guys this more in the code but it can be used anywhere and that user can be empty for example if the user is not logged in or if our user does get logged in we can store all of the data stored in our json web token inside of this current user object and remember the main point here is that context can be interacted with anywhere and the way we set it up which is our context is going to be our entire react application and don't worry if this seems complicated right now it's a lot of different steps and i will show you guys everything one thing at a time throughout this entire video alright so this is the full project we're going to create in this video it's very simple it's going to have a home page and then a login and a register so if we want to register a user we can say cooper wl45 here let's say i'm going to call this test2 at gmail.com i'm going to make the password test2 and then test2 so we can then register a user and now this registered user is going to show up and it's going to say hey there test2 with gmail.com and it's not just because we put it into that one text form what's happening is this is our actual json web token showing that test2 gmail.com has been logged in so if we log out again and then we log in the regular way we can go test2 gmail.com test2 gmail.com and then test2 down here and then we can log in and you guys will see it's going to say the exact same thing hey there test2 gmail.com and this isn't a trick trust me guys we actually made this and what's happening is we are getting a full authentication we're getting validated in the back end it's saying yep that's the right password for test2 log him in and give him a json web token so we can use our website that's the basic idea of this website it's very boilerplate and something you can build on top of let's get into the code so getting started with the code i will link this in the description this is my basic apollo server authentication which is the created code from that video i keep on referencing from before and so i'm starting with this exact code from this commit here i don't believe this is going to change the future so if you are following along just clone this repository and you'll be at the exact same point i'm at and just to showcase some things what we really care about is inside of our typedesks we have a register user and a login user massively important because that's where we're going to use in the react part so now that we have our full authentication server we can pull up the terminal here i would recommend creating a split terminal this pretty much means just two terminals at the same time you can just have two different terminals if you're not using vs code but split terminals super helpful for this and we can npm start if you just fresh installed the github repo like i did you want to npm install to get all the different technologies that we are going to be using on our apollo server side and then we are going to want to npm start to start that apollo server if your mongodb uri link is correct you should see mongodb connected and server running at localhost 5000. so on the terminal to your right which i want to do is you want to say npx create dash react dash app and sorry that's all weird let's do this create react app and then you're going to want to say client i just named the folder client because it's doing a lot of my videos and it's pretty simple so let's make that react application by pressing enter so once that is done we want to cd into client on our right here and now we are inside of our actual react application and so as you'll see all these different files got created one of the first things you want to do is going to source go into app.js and we can just delete this entire header here that's just the boilerplate code and you just want an empty application to start first things first we're going to want to create an apollo client for our react application to use so when it does use query or use mutation anything like that we want it to use an apollo client so we have to create that first so we can go into our source folder and make an apollo client.js so for our apollo client we need to npm install at apollo client this is going to get us everything we need to create the apollo client itself and so we're gonna have to start with a couple of imports the first one is import apollo client create http link and then in memory cache then we're also going to want to import sets context it's important for apollo and for context is from at apollo slash client and we're going to go to link and then context we're going to want to create a very simple link to get our actual apollo server here so we're going to say http link is equal to create http link and we're going to want to give it one option link option which is the uri of our link this uri is going to be going to http slash localhost 5000 because that is where our authentication server is living on now we're going to want to create an authorization link this allows us to pass in our token under an authorization header and i'll show you guys what that means in a second here so we're going to say const auth link is equal to set context we don't need this setter initially so we can say underscore to ignore the first parameter and the next thing is going to be a bunch of variables and one of the variables we need to get out of it is the header and i know that's kind of a lot this is covered better in the set context documentation if you're more curious about that and so we're going to return oh and i'm missing a thing here sorry i was missing an open parenthesis here so we're all good here and we're going to want to return to this we're going to want to return the headers with whatever headers are passed in okay so whatever other headers are in there and then we're going to want to add one on top and so the one thing we want to add on top is this authorization header so make sure it's authorization and make sure you spell this correctly because we're going to be using this in different parts of the application and this is the first time we're going to see local storage so we're going to say localstorage.getitem like we've seen in the documentation a bit ago and it's going to be called token throughout our entire application i chose to call this token so you can name it whatever else you want but pretty much if token exists we want to set authorization to this or if it doesn't exist we want to set authorization to an empty string so this is kind of where our json web token can live in our authorization headers so now we can create the actual client so we're going to say const client is equal to new apollo client like this and it's going to take two different options the first one is the link which is going to be that authorization link dot concat http link this is a way where we can pretty much add two links together it's recommended in documentation you do it this way and then the cache is going to be our simple new in memory cache so in-memory cache comes from up here and we're pretty much instantiating a new object of that now we want to export something that our react application can use so we can say export default client this means that we're exporting our client const that we create here so other areas of our react application can use it and so this is the full apollo client now we can get started over at our index.js and give our react application access to our apollo client overall i'm going to do a lot of things at once here so i'm going to make a comment explaining what's happening our react application needs access to dot dot dot and i'm going to make a list of all the different things we need to give it access to the first thing is our client when i say our react application needs access to our client our react app is living at line 12 here and one way to give it access to our apollo client is to get an apollo client tag and then wrap it around this app that means anywhere inside of our app it has access to the client itself and so client is one of the one things we need another thing we need is our authorization context like i mentioned before this authorization context can be accessed anywhere in our application so we need to make sure that it has a wrapper around this app anywhere and then one of the last things is the browser router this is the react router which we need to make links to pages in our website such as you know slash login slash register it's going to help us say hey when we press the login button we want to go to the login component for example and so we have to kind of instantiate all these in our index.js so it's a bit of work but it'll be worth it and it'll make your rest your application more easy to work with so first we have to npm install a couple of things so first we have to npm install a couple of things one of the first ones is going to be react dash router dash dom and the second one is going to be at apollo slash react dash hooks and sorry this is wrapping guys let's see if i can do this there we go so at apollo slash react dash hooks so make sure you install both of those because we're going to use them in a second here they should take not that much time so we want to import the actual client we just made so we can say from dot slash apollo client like this to actually get that client that's being exported from what we just made now we want to import the apollo provider this is how we give apollo to our react application that's coming from apollo react hooks here and then we want to import the browser router from our react router dom this is just one of the ways we can set up links throughout our react application and so a note here we have not made the authorization context we're going to add this later but it's important to recognize that it's still here so our client is going to be in our apollo provider the browser router is going to come from here we don't have a context that we've made yet so we're going to come back and add that later we do have our apollo provider so we can do this use the apollo provider set its client equal to the client we pass in right here and make sure that wraps around your entire react then within that we want to go and have our browser router so we can say browser router here make sure that wraps until that reacts strict mode like this and you'd be surprised now we have access to the browser router so we can do react links for example and we also have access to our apollo client let's go make some context i'm going to create a folder called context this isn't super necessary because we're only going to have one context but this is to show if you want your react application to be scalable have good structure you can put multiple contacts inside of here this is going to be called our auth context so our authorization context so we want to give our context an initial state and so we can a const initial state is equal to an object this object is just going to have a user that's going to be initially be null so pretty simple and pure javascript no libraries or anything like that from anywhere in our react code we can access this local storage and it is a super important part of this so we can say local storage.get item token so if in initializing this we see that there's a token in our local storage we then want to actually get that token decode it and get the information out of it so as you'll see here we can say const decoded token is equal to and we're actually going to use a library for decoding the json web tokens so go down here and say npm install jwt decode this is a super popular library that's used for this exact reason it's pretty much getting the data out of a json web token so i'm going to import jwt decode above i'm going to get it from the jwt decode library we just added and so i can use this now and say hey use this jwd decode on this local storage token and so i'm just going to use a one liner for this you could make this a variable if you want we're pretty much saying hey decode the current token in our local storage so the json web token is going to have an expired date on it so we can compare this expired date by saying take the decoded token get the expired property from it and then do times a thousand this makes it so we can compare the expired time to date.now for example and so this means that now date.now and expired are in the same kind of time they have the same values and this is why we do the times a thousand and so now we can say hey this means that we have an expired token local storage dot remove this token so we could say remove item and then say token so you don't even have to say like a certain token in particular you just have to say remove item and then whatever we labeled it as which is token here else that means we have a valid token and so we could say hey initial state dot user is equal to this decoded token and so this is a way so when our website starts up we can see if local storage already has a token for example and set the initial state so at the top here we're going to want to import react and then we're going to want to have use reducer and also create context are the two things we're going to want to get from react because now we're actually going to create the full context and make sure you spell reducer right there we go so we're going to create our context and it's going to have a couple of things initially so we're going to have an auth context which is going to be a create context and this create context is going to take a couple of things to the default value so the first thing it's going to have is a user which is going to be null it's going to have a login function and this is a function that's going to have a user data and we're going to do an arrow function to an empty object and then it's also going to have a log out function which is going to take no parameters because we don't need user data to log out just be like press the logout and then clear the cache is the idea there these two login and logout functions we're actually going to define in more detail below and so that's why they're kind of just defined as this for now so now i'm going to create something called an auth reducer so i'm going to say function auth reducer is going to have two things a current state and then a current action and you guys will see this in more detail in a second but pretty much it's going to be a switch statement overall it's going to say hey look at this current action we're trying to do to our authorization context and so look at the type of it and now we can do a switch statement which is pretty popular in javascript in other languages where we're gonna have a bunch of different cases so on the case of login for example what do we want to return well we want to return the current state whatever that is and this state is coming from our reducer by the way so we're going to return this current state and then we also want to change our state to say user is equal to action dot payload so whatever is in the actual payload of this action we want to you know give it to our user this could be the json web token for example or whatever we get out of the actual action and we're going to have another case for logging out and you guys will see it's very different on this one because we're going to return same thing we want the entire state so we use a spread operator on the state but now we want to have the user be equal to null because we've logged out we don't want our context to show you know the actual json web tokens as you might get here we want it to be a null user and then just to have a default for our switch statement i'm just going to return state because we don't have to return anything on top of our state we can just return the state itself the reason why we have these return statements like this is because we're returning our state plus a different attribute to user or the user being set to null okay so now that we have our auth reducer set up we can do the fun part of this which is the actual auth provider the provider is what the rest of our application is going to see in react and so we can say function auth provider gonna take in some properties here and one of the most important things we need to do here is we have to say const state and then dispatch is equal to use reducer then it's going to have the auth reducer and then the initial state to our reducer this is where everything kind of comes together as we have this authorization reducer then we have this initial state which is why we did all this code up here so this is a react hook here and it's going to have a state and a dispatch that all comes from the use reducer documentation and dispatch allows us to do things to our actual reducer state which you'll see in a second so now we can actually define those functions that we have in our context so we can say const login is equal to we need to find it with this user data parameter so we need to use that again and we're going to make an arrow function here when the user logs in with data we want to do is this local storage dot set item of the token and then say userdata.token when this login function gets called it means that we have the correct stuff that we need from our apollo server keep in mind this login is not the apollo server login this is just the things we want to do when we get a successful response from our apollo server so that is definitely worth clarifying because after this we're going to dispatch which means we're going to change things to our state and we're going to say type is equal to login and we're going to want to have a payload of user data so take a look at this it kind of comes full circle where we have this dispatch and it says type and payload and up here look at this you can take an a look at the action here right so you can say hey look at the type it's called login and so we can go okay action.type we are under the case login okay that's good and what do we have we have the payload which is the user data and so the user gets set equal to this action.payload so the user gets set equal to this entire user data object so hopefully that makes things make more sense overall now we can create a function for logging out the good thing about logout is it's way more simple we can say localstorage.remove item token and then just so we clear our state we can say dispatch type is of logout and the reason why this is so much more simple down here is because with this type logout we don't need to pass any parameters you know just saying when this logout case gets hit do the spread operator overstate and then set the user to null so we don't need to set it equal to any incoming parameter which makes this logout functionality significantly more easy okay and then the big finale here we are actually going to use our context and return it as a react object or a react element we can use so we're going to want to return and then we're going to say auth context then super important dot provider because right now we are going to have a provider that the rest of our react application can use to look at this authorization context we just made and so its initial value is going to be equal to the user then the state of the user and we want to pass in login and log out why are we doing this is because if we look at our actual auth context it's saying hey we need a user value it's going to be initially null and we need a login and a logout function and so when we created down here in the provider we're saying hey use a state.user here which is going to this state at our reducer and whatever the initial state is or whatever the state is showing us it's going to set it to that user value then the login is being set to this const login we created here and this logout is being set to this const logout here and so i'm just explaining that in depth because if you ever want to create other things with this like let's say i wanted to create a you know validate is admin or something you could do some type of code here okay i'm not even sure if that makes sense but you could just have other functions on top if you wanted is my main point there you also have to pass in all the other props we might need and we're passing in these props just because they are coming from the props that are initially passed into the provider itself and so now we actually have a full context and a provider that we can give to the rest of our applications so we export it by saying export auth context comma auth provider and so you guys will see there's like export default there's export other stuff when you export with this object syntax like this it means that if we try and get these objects from the actual authcontext.js file we have an option we can grab auth context or we can grab grab auth provider so it gives us options in how we can do this for example if we only wanted the context we could just grab that only or if we only wanted the provider we could grab that only you see this in the imports above actually where you say use reducer and use context when you see this type of syntax it's saying from react we only want user reducer and create context we're not just going to grab every single thing from react because it'd be a lot of stuff okay i know this is a lot of work guys but just hang in with me here now we're going to go back to our index.js file so in index.js have an authorization context that we have not made and we had to add this later good news we just created our authorization context so congrats so we can add that by doing this import early braces auth provider okay and you guys will see this is kind of coming full circle what i just mentioned before and we're gonna say dot slash context slash auth context so this auth provider is the actual object let's go back to our auth context it's being given to us right here this auth context dot provider and so we can actually go to our app.js so we can actually go to our index.js take this auth provider and then wrap it around our entire react application this means everything in our react application has access to the actual auth provider and the context it has that means we can access it anywhere in our application so we can get rid of this to do because we have made this so good news i know this is a bunch of setup but we're finally getting to the fun part where we start creating react components so i'm going to create a couple of folders to kind of organize our code overall we're going to have one folder for pages okay one folder for components and one folder for let's see here yeah we might need something for utility so i'm going to say utility that's just like you know kind of various things that are going to be used all over the place pages are like the home page or the login page the register page and components are things like the nav bar for example it's a component that's used in multiple different pages so to get started i'm going to go to our app.js we can get started by creating actual routes inside of our application and so we don't need this class name app we can just have a regular div hold everything and we're going to want to import some stuff from the react router dom to create routes to log in and register stuff like that so we can say import routes comma route comma and i think we just need routes and route and so we can say from react dash router dash dom now we have access to the route stuff here this isn't a super in-depth tutorial of the route stuff i'll be honest um if i were to do every single thing i bring up in depth this would be a way longer video than it already is and so i'm just going to show you how to set up these routes in a basic way so you have to have a path to a certain route for example if we're on localhost 3000 this path or just a slash would just be localhost 3000. it would bring you to whatever element you define in here and so as you'll see we don't have any elements for these to point to but eventually want the element to become a full page and so let's actually create the full element for one route to show you guys an example so let's go over to our pages and we can create a new file under pages and i'm going to call it homepage.js so this is going to be a very basic react component because this website has no functionality besides the login okay so you can go down here and say function homepage so for home page component for now we can just say return do some parentheses and then say h1 this is the home page it's gonna look awful by the way but hey it's okay it's it's a home page and it's a component that we can use so we can save our export default homepage like this now we can go back over to our app.js and say import that home page we just made remember since it's an export default we don't need to do the curly braces it's going to get that default export which is the home page we made and we can set this element equal to the home page here and so you can just define it as a component like such so if we go in in npm start okay so one quick error is go over to your apollo client.js this header should be called headers my bad that was a super obvious one um but just to make sure you fix that that aside though you should see on your react application it will run after you get that fixed up and this it will say this is the home page and so this is great because what's happening is our react routes are actually working it's saying hey in our app.js if we route to path this then show the home page component and our homepage component of course is very simple but it's still showing the component at the end of the day so that's great news and so now we can create routes to our actual login and register components as well so if we go over to app.js we can say hey make another route we can make it to the path of login for example and make another route and we can make it to the path of register and these are going to go to their own components as well for now i'm just gonna keep the register component and then delete the login one we're gonna make it in the future but just so it simplifies our code before we fully get started on creating these routes to log in and register though let's create a nav bar for our website and that's a little bar at the top that has the you know name of the website and also the login and registered buttons so let's create that before we get into making the actual login and register themselves so we can go into components and make a navbar.js inside of our terminal we can say npm install at mui material this is going to give us access to all the different material ui components that we are going to need okay and throughout developing this i'm going to just npm start my application to see if any of my imports get messed up so when creating our navbar i'm going to make a very basic function navbar react functional component and so now we're going to use a bunch of material ui components to help us create a user interface pretty fast so we can import all these different components from material ui there's a bunch of different ones here and so i'm just going to list these out app bar box toolbar typography a button and i believe that's it and those are all going to be from at mui material pretty much the entire now bar itself is gonna be in a box and you're gonna do some styling on it saying hey make the flex grow attribute equal to one so there's some flexbox stuff going on here and this is what our entire navbar is gonna be wrapped in we are then going to create what they call an app bar and i'm going to make its position equal to static and so again these types of attributes are all coming from material ui the position properties and things like that and then i'm going to create a toolbar in here which is again from what they want us to do and now it's going to get a little bit more simple so i'm going to say hey typography make it a variant of h5 and we also want it to kind of act like it's a div component instead of like an h5 component so we can do that there and now we can actually make our first link and so we can go up here and say hey import link from react router dom and so this link is super important it's going to be what helps us go to different routes throughout our application so when making a link we start by just saying link and we want to say hey where do we want the link to go let's just say to our home page for example and so i can say react login and now this is going to be a link to our home page let's go and put this nav bar in our app.js and oh go to export default navbar at the bottom here let's go to our app.js and then import navbar from component slash navbar then let's see here inside of our div we can just initialize the nav bar like this and we should have a navbar inside of our application quick note on the installing material ui i messed up and showing you guys this you actually need to install mui slash material which we already have then you also need at emotion slash react and at emotion styled these are necessary for material ui to run i forgot about that but we can copy this over go into our terminal copy it in press enter and now you should have everything you need for your material ui stuff so now if we npm start we should be fine all right good news so we have our actual login component and so you can't really see anything happening here but you'll see that this is a link to localhost 3000 and if i click on it i'm just going to go to my same page over and over so not super useful yet but it will be useful in the future here and so we can do some style on top of this link and i'm just going to say text decoration which is going to get rid of that underline is none and then i'm going to say the color property is going to be equal to white this is just going to make it a bit look a bit nicer there we go looks more like what you'd expect um and that's going to be a simple login link for us and so now we can create some buttons here and so we're going to put our buttons in another box and we're going to say hey in this box we want to align the items to the right and we want some more styling here which is going to say hey flex grow is equal to one then text align is going to be equal to right this is just some stuff that i've found so don't take it too seriously you should just create an actual basic navbar i am not a ui youtuber i'd never claim to be so so but i do understand this stuff well enough to get a good idea of how it all works together so at this point we can make some buttons for login and register and so we can say hey make a link for example to log in let's go over to our web page here and as you'll see you have a login here and then make another link to register and so we can actually go make these go to the login and the register routes and take a look at this i know this is a lot at once but this is pretty cool if you go to your react application now make sure you refresh and you press log in you're actually going to go to the login route right now our login route is just our home page so it's nothing too serious this is a homepage component again but if you go to register you're going to go to the register route this is good news this means that we can actually make these we can actually make login and register point to different components such as their own respective components the login component and the register component for our login here i'm going to do a margin uh right put it equal to like 10 pixels or something this is just going to give us some distance between the login and the register here and boom now we're good to go so now we have all of our respective links that we need for our full system to work we have a login we have a register and if we go to react login here we go back to our home page so that's super great news before we actually get started creating login and register i'm going to create something called a kind of react utility which is something i've seen a lot in react projects but it's going to be a hook that we use so we can actually create our own react hooks and you might be like what is this guy talking about why are we making a react hook in register and in login we are both going to be creating forms and so we can make a hook that makes forms significantly easier to use and this is actually something i found online but i found it to be super great practice because it makes it so you don't have to constantly recreate the react form logic every single time you make a react form because it's kind of messy how you have to do your variables for the actual react form themselves and i'm just going to pretty much copy this code over because it's not my code this is from somewhere else okay take a look at this code and feel free to copy it yourself and i'm just going to walk through it here so what's happening is we are making a react hook ourself it's going to have a callback function and it's going to have an initial state set to an empty object and so it's going to have a state which i believe if you watch my other videos you're going to be familiar with but this is just going to be the values of the actual form so pretty much what's happening is it's this is it's giving us a generalized way of saying hey if we have a password and we have an email input okay for all of these different pat for the password and the email values we want to say hey go through the values and then change for example the object will look like this it'll look like password is pointing to an empty string initially an email is pointing to an empty string oh sorry an empty string like this and what this hook is allowing us to do is saying hey whenever password gets changed go into this values object and go in here pretty much set it equal to an empty string so when we change password here we want to say hey get the event.target.name which we are going to make password change it to the event.target.val which is pretty much saying if we are changing an input box the event.target.value is going to be the value of the input box it makes creating register and login way easier this is why i bring this up i'm not trying to make this harder for you guys i'm actually trying to make it easier for you guys and also you'll see when i pasted this over i have this console.log values because i will show you guys how this empty object actually changes as you use the form that's just a small explanation of the use form stuff when you submit the form it has a callback function for example if we submit login then you're going to want to call all the login functionality on our graphql side so this callback function helps us with that i've said this so many times in this video but this will make more sense when we actually create it in the register so let's get into it we go to pages and we're going to make the register page so you make a page called register.js then import use context and use state from react so i'm going to import the auth context from wherever we stored it so for example i'm going to say from dot slash context i believe i've got to go back a folder so dot dot slash context slash auth context and you might be like why are we getting access to the auth context well let me explain so when we create a register we're going to want to change things in our overall context and so if you go into your context auth context here you'll see we have this login functionality for example right when a user logs in we kind of treat logging in and registering is the same thing because it's the same action we're grabbing a token and we're pretty much setting this token equal to the userdata.token we can get user data from a successful register or we can get user from or we can get user data from a successful login so it's treated the same way so we need access to this login function saying hey when we get the successful response back from our server do all these login stuff we say to do here that's kind of the basic idea of this so that's why we're getting the auth context we're also going to import that use form which i just discussed there so we're going to go from dot dot slash utility slash hooks you're also going to need a use mutation this is where our apollo server stuff comes in we need to install two things i believe when you do npm install at apollo slash react dash hooks and i'll show you guys that so apollo react hooks install that then we're also going to want to npm install a graphql dash tag this allows us to create actual graphql queries in our react application and i'm importing these because i'm just going to get all the imports out of the way first so we have to import the use mutation which means we're going to making we're going to be using the mutation register user from our apollo server side and so we can say at apollo react hooks great news i'm going to import gql from graphql dash tag like we just did there and i'm also going to import this thing called use navigate from the react router dom which is the same library that handles our links i'm going to make our graphql query here so i'm going to say const register underscore user is equal to gql and then backticks as soon as you say gql backticks that means you're in gql land javascript does not apply here so we can say mutation i'm just going to call it a mutation put the name mutation and this mutation is going to require a register input and i'm going to say of a register input type and so you're like what the f is this is what you're probably thinking so if we go to our graphql type defs you'll see our register input is this input type here and we are using the register user mutation here and so i'm not trying to jump around too much but just to give you guys context as to where this is coming from so we can go in here and then for this mutation we want to pass in the actual register user mutation so this is actually us calling it and saying hey call registered mutation here and give it access to this variable we passed in which we represent with the dollar sign variable of register input and hey when this register user gives us back data give us the used user's email the user's username and also give us that token that gets created when they get registered so this is what our mutation call is going to look like now we can get into actually creating the react component so i'm going to say function register props i don't believe we use props for register but just it's just there so you know that you can access the react props if you wanted so let's start by setting up our full register user mutation so we can say const register user comma we can also get the loading property out of this we don't really need this but just to show you you can get other properties out of the used mutation hook and we're going to say use the mutation register underscore user which is a const that we just defined above which is great news and as always this is going to take in a bunch of options very common in javascript for things to take options alongside their kind of normal inputs we are going to have an update function that gets called there's going to be a proxy here that i don't believe we need to use but we can still put it there and then we also want the result and so the results going to be formatted where we say data is going to be okay from register user what do we get we get a user data object which is going to represent this data right here we can then define this update function is what do we want to happen when this gets updated well we want to use our context oh we haven't even defined this yet so when we bring in context into our register we want to say const context is equal to use context auth context and so this gives us access to anything within our context and so as you may remember we defined functions within our context so we can say dot login user data this is the exact login function we made in our context before and so now we can use we have to define a lot of stuff guys sorry and now you have to define navigate which allows us to pretty much tell our web browser when to move around and so we can say let navigate equal use navigate like this and so this way we can go in here and say navigate so it's saying navigate to a certain route for example and so we can navigate to the home page when our user is successfully logged in this update function gets ran when register user actually gives us a data and it's a good response and so you might be like a good response what does that mean well it means we also have to define on error because there can be bad responses for example our backend uses graphql errors like this and so i'm just going to show you guys this in a very basic way you can have a state to manage all of our different errors so we can go up here and say const set or sorry const errors comma set errors these are going to be all the errors that come from our react or sorry these are going to be all the errors that come from our apollo server back end and so it's going to be a state of just an array because that's how the apollo server gives it to us in the authentication video i discuss errors more in depth but all you have to know is it's going to return a array of errors that we need to set and so i can go down here and say hey when errors get set i can do something like this set the errors state equal to this graphql errors graphql errors is an array and so it's going to give us all of those different errors and then we can do things in our front end to show these errors to the user this mutation requires variables and so it only requires one variable it's going to be the register input and it's going to come from a values so where is values coming from well we need to create that use form to get the values from our form so our use form has a couple of things it's the on change of the form the on submit of the form and then the values of the form is the three things our use form hook has is giving us we need to initialize a callback function eventually so i'm going to call it register user callback this is a function we have to initialize here but we also have to initialize what our form actually is keeping track of for this front end i'm going to keep track of four different things the username which i want to be an empty string initially the email which i want to be an empty string initially the password which i want to be an empty string initially and also confirm password and surprise also an empty string seems good to me in doing all this stuff we now have access to a form that's going to be a little bit more easy to use than defining like five different states for five different things and it'd be maybe a mess okay and so this values here is actually going to give us an object of all these different things it's actually this object right here that i have highlighted and so register input is an input type that's expecting an object of all these different variables which is good news for us an important thing here is if you have to you have to go to your graphql type defs and we're actually going to add a confirm password here in the original code i didn't have a confirmed password but now we want register input to have a confirmed password this is actually pretty cool because we're only doing one code change here but it gives you an idea of how you can change your apollo server to maybe meet new constraints for example so over at register we have these four different things when we call this mutation it's getting a register input and it's expecting four values the username email password and confirm password and that's kind of the full process of this and guys i know this is a lot but this is seriously like a full application so hopefully this has been pretty valuable so far but now we have a registered user mutation ready to get used and all we need is a front front end to actually interact with these things we've created here so now we're going to get into that so i'm going to make a return statement here i'm going to keep it empty for a second and what we have to do at the top is we're going to import some things from material ui and so i'm going to import a couple things that i know i want to use so we need text fields we need a button okay we need a container we need a stack and we also need alerts give you an idea text fields help us have text inputs buttons things you can click on container keeps your stuff on a container stack is how you can stack a bunch of different text fields for example and then alert is if we get an error we want to show it as an alert just basic understanding is why i'm including all these yeah let's get into actually coding this out so now just to be super clear we are coding kind of the front end part of this so first things first we want a container in everything and containers have this property called spacing i set it equal to two and they also have a max width i'm going to make the max width small i can just do regular h3 here i'm not going to make it complicated with typography i'm going to say register and i'm going to say this is the register page register below to create an account and so this is very simple basic stuff here and so let's actually take a step back because i know i've been kind of confusing with all this new stuff and let's take a step back and go into app.js let's go to register and remember export default register i believe they called it register yep great and so now we can go into our app.js and say hey point this to the register component that we're going to create so i'm going to say import register from pages slash register and now i'm going to give it an actual register component and so if we npm start here quick thing in register.js is we actually want auth context to be a capital a and so make sure that wherever you have auth context it's going to be a capital a there register user callback is not defined so let's just do that here function register user callback it's going to be very simple i'm just going to say console.log callback hit for now this is just to get rid of the error for in our front end and so this callback's just going to log something we're going to work on this more in a second but let's npm start here and we will see in our react we now have a login and a register but if we press register we will actually go to the register page so that's super cool because you can see our react routes working we can go back to the home page if we want we can go back to the register page and it's just showing you guys that the components actually getting loaded and i also do this early on in the register making it just so you'll see that you don't have any import errors or anything else you have to deal with and so yeah we are good to go to create the rest of our register component okay and so now i'm going to make a stack and the stack is going to have a spacing of two and it's going to have a padding bottom of two as well and so this stack pretty much allows us to stack multiple material ui elements i'm just going to use a bunch of text fields for this case and so let's create one text field just get it fully done let's set the label equal to username this is gonna be our username textfield and i'm gonna set the name equal to username and i'm going to set the onchange equal to that on change from our form and so kind of what's happening with our form here just to explain it again is when this on change gets called it's going to unchange whatever this name is of our text field so if our name is username it's saving a username property and then when it when the on change gets hit it's going to change this username property to whatever the value is of the text field so that's a very simple way of understanding it but that's what's happening so we can copy this over again and we can now say okay instead of username we want an email for example copy this text field again to create another one and instead of an email we want a password password down here and then for this next one we are going to pretty much use a confirm password here so i'm going to make the label called confirm password like this and i'm going to make the name confirm password all right and that's going to be our entire stack so if we go back to our application you're going to see whoa we have some actual text boxes which is pretty pretty cool so if we go to our console take a look at this you'll see the state's always going to kind of be one step behind that's just a flaw of how i'm logging it to be honest like console logging it but this state is actually going to be whatever is in here so if i name it like cooper wl there you go it's gonna show you cooper wl and then if i do this it's gonna it's gonna pretty much be holding these inside of our actual form so this is the object that our form is representing is it showing you know my username and my email and all my different stuff and eventually that's going to be sent to our register user mutation so just to explain that there now i'm going to make some code to actually get the graphql errors and so we have this errors object that is coming from the error state right here if you're like where's this coming from it's coming from the error state right here which we only ever set errors if we actually get some graphql errors and so we can say errors.map function error and yeah i don't really need anything else there and i'm just going to go in here and say hey do this and now we're going to be able to map over all the different errors and create something from the error so we can return an alert from our material ui and you have to set its severity property equal to an error so it goes all red on you and then we can do go to the error dot message and so graphql errors actually makes it super simple to just show things so we can show an error.message like this you're not going to be able to see this working until you actually manually make some errors trust me this is a basic way of going over an array of things and then making alerts based off you know messages from each thing in that array now we can go down here and create a button i'm going to make it a variant of contained and when we click this button we want to run the on submit from our use form and so this is why use form is pretty cool is because we're going to have this register button when this register user callback gets hit that only gets hit when on submit gets clicked on or gets used and so when this on submit gets used right now all it's doing is saying callback hit and so we can even go into our react application right now we can refresh this and we can just press register a hundred times and as you're gonna see it's gonna say callback hit callback hit callback hit over and over and over again but yeah if we ever wanted to actually run our mutation you might be like oh running the mutation that sounds like some complex stuff nope so our mutation the way we call it is by just having this register user function right here and so how we call the mutation is just this that's it is we just call the register user mutation by using this function here and then this used mutation right here keeps track of all the update keeps track of all the errors we already set everything up all we have to do is call this thing once which makes this use form makes our lives way simpler in that regard so we now have the full component built out so one of the first things that we can do is let's see if it causes an error for example okay i already have a guy named test gmail.com and so if i press register it should say yo someone's already made with test.gmail.com don't let them register hey it's working and just to explain this i've been using the same database for even testing this project so that's why i know test gmail.com is a registered person so if we try again let's actually try and create someone and see if they show up in our database so i'm in this guide called cooper codes and i'm gonna say cooper codes is awesome at gmail.com and i'm just gonna be like test test i make all my passwords tests okay i'm not trying to make secure accounts i'm trying to make a tutorial okay so cooper code is awesome at gmail.com and if we register oh we got sent to our home page which is good news yeah and you guys should be expecting that why were you expecting to get sent to the homepage well when you see in our code here when our update function gets called we want to log in with our contacts then we want to navigate to the homepage those are the two things that happened so this actually means we ran context.login with our user data successfully which is super great news because we hit the navigate after okay and so if you go to your mongodb atlas however you have it hosted you should see that the person registered actually got put in there as well and so i'm kind of not going to put a main focus on this because this mongodb saving code is more of a focus on the backend video but in the front end you'll see it used the mutation correctly it even saved it to our database correctly hashed the password and everything and now we have a user in our database of that you know certain person that just registered which is super awesome and so as you will see we don't have a logout or any logout functionality quite yet but i'm going to work on the login first and then we can get to the live log out after okay so we can go to our pages and now we are going to create a login.js to create the page for logging in hopefully you guys are a little bit more motivated now after we did the hard parts of register and maybe getting some understanding of it as well i hope and so that's kind of the hardest part is this registered one so if you gotta pass that good job pat yourself on the back okay so i'm gonna do some cheating okay we already have all this stuff from register.js that we're probably also going to use in login.js so copy all of your imports from register.js go to login.js and just paste them at the top i just save you so much time okay i'm joking but yeah kind of actually but now we're going to do the same thing so we have all of our stuff and like before i'm going to make a login underscore user mutation we're going to set it equal to gql and we do the back ticks and that means we are in gq outland now so we're doing graphql querying language and so i'm going to say mutation login what is it going to take well it takes a variable login input which i'm going to set equal to a login input object remember defined in our type defs if you're ever curious about where this is coming from and now we are going to say ok now we're going to use the login user mutation it takes in a login input that we can set equal to the variable login input that's what that dollar sign means by the way is it means this variable defined there now if we actually get a login user we're going to want email username and token out of it and so i wasn't bs in you guys as you'll see here register has the exact same things it gets back fr and then login has the exact same thing to get back like i wasn't trying to be like oh log in and register give me the same thing no they actually do so just so you guys see that in real time they are really really giving you the same things and so when we register we use login which is kind of confusing but it's just because we want to use our context the right way and give that logged in data you could imagine it like this when someone registers an account they register the account they allocate all of it and then they log in with that new account stuff right after and so if you just log in regularly you skip all the account creation but you're gonna log in at the end of the day if that makes sense and so now we can go down here and we can say function login give it some props like i said before i'm just doing this to show you guys what's possible with react you can use props in this login property if you wanted to or in this login component if you wanted to but in this video we do not same thing i'm going to need to use navigate so let navigate okay if i could spell that would be helpful there we go is equal to use navigate which we already have imported above so now i'm gonna need access to our context which is going to be use context auth context and same thing here we are going to get errors from our login the same way so that's kind of nice because they don't have to explain it twice you're going to get errors from same thing you're going to get those graphql errors like i discussed before and same thing we are going to have a login user callback function which is going to call login user which we haven't quite created yet i'm just going to go down in the same order we did the other one and so i'm going to make our form first login user is not defined yet just saying it's going to be defined when we create our mutation kind of like where register user is defined if you want to go look back at that and so now we're going to get on change on submit and then the values from a new form so we can say use form is equal to login user callback that's the callback function we want called when this gets when this form gets submitted and now we're going to say email is equal to an empty string password is equal to an empty string when we log in it's just going to be the email and the password that's it okay so now we can say const login user i'm going to do the same thing you can use loading if you want but i don't really have large enough load times to show you guys how to use this loading thing so maybe that's a good thing but then we're going to use the mutation and we're going to say hey use that login user mutation we created above and same deal it's going to be very similar to the point actually where let's go over to register.js copy all of this code in the middle of the mutation bring it over to login and just paste it in here like this it's going to be very similar context.login and userdata it's going to be the same thing except instead of the data coming from the register user mutation the data is going to be coming from the login user mutation so that's important but everything else here stays the same everything else here stays the same instead of register input it's going to be login input and then the values see how easy this is guys it's not so bad once you learn it but now we have kind of like before we have everything set up now we just need to create a front end to use the mutation and use the form so let's go in and do that so i'm going to say return i'm gonna go over to our register.js and i'm going to copy this entire container okay the entire return statement guys just copy the entire container and i'm going to bring it over to our login okay and so you don't get too worried like holy i just copied like 100 lines of code don't get too worried guys so we are going to want to keep the email and then we are going to want to keep the password so delete those text fields that are not email and not password so just have the text field with email and password left over and change the text to say login and this is the login page login below you're not really creating an account so i'm just going to say login below and the errors get mapped the same way and instead of register you want to say log in here i know you guys are like this is too good to be true you can really just do all that but think about what's happening okay our form works the exact same way so our on change here is going to have a name of email it's going to get changed and it's going to change its email in our initial state here or in our state here and then when password gets changed it's going to hit on change and it's going to change the password value here and whenever we log in we're expecting you know only to have the email and the password for our login input for our mutation and so everything kind of complicated is happening on our back end and so you guys can kind of see how when you make things like use form when you make things like use mutation in a kind of consistent way it makes it easier to build your own applications you'll see the same patterns kind of get repeated over and over and so at the bottom here let's export default login because since i'm missing something i think we have the full component yeah and then let's go over to our app.js and inside of app.js we're going to import login from dot slash pages slash login and now we can set the route login to actually be the login component and so let's go back to our react application and boom it's already logged in for us and so this is the login page login below okay thanks i'm so i'm going to use an account i already know that's registered so test gmail.com but you can literally register whatever account you want right now just like it's a regular website guys so if you don't have this i would recommend i always do test gmail.com with the password of test it makes stuff like this easy to work with to use the same one over and over again and so let's attempt to log in boom we are here this means that our code went through so we are getting there in the full authentication trust me but there's one thing in particular that we need to understand let's go to our nav bar real quick right now our navbar is showing log in and register no matter what let's take a look at this okay let's get access to our auth context and so i'm just going to copy this from somewhere else you can go to i went to login.js to find this line but copy an auth context import and bring it over to your navbar so we can say const context sql to use context that actually imported that automatically for me so thanks vs code but make sure you import use context from react and we are going to want to use the auth context like this so we have always initialized context like this but one thing we can do is we can get specific things out of our context you see how vs code right now is showing the user the login and the logout if we want user and logout for example we can do this make an object get the user property from our context and get the logout function from our context you see how log out changed to a different color it's because logout is it knows that in this context logout is a function which is super great news and so we can get these specifically and so logout is a function we can call and so if we want to ever make a logout button in our navbar we need to make a function here something like const on logout we want to run something when our logout gets hit and so we're going to make this an arrow function like so you can you really use whatever syntax you want here but we want to log out and then we want to navigate to uh you don't need to do this but navigate to the home page just to see that it really logged us out just in case we're on like a different page and then we also need to define navigate so let's do that here use navigate that's going to be coming from the react dom again so react router dom and so same deal we're going to say let navigate equal to use navigate great stuff and we should be fine now and now we have this const on logout to find but let me show you guys something cool so user is an actual thing that exists in our navbar or in our context which just happens to be being used in our navbar so user actually exists so i'm going to console.log user whenever our navbar gets re-rendered it's going to log this and so let's go back to our react application and as you'll see right now i have a user kind of cached is the way you should think about it and so when i refresh my page it's showing me a user of the test at gmail it's showing me that expired the initialize the user's id all this stuff from my json web token and so this means we actually have a user object and so you can do something interesting here if you don't have a user for example you're logged out it's going to be an empty object since we know that we can do some interesting code here and so we can make a ternary statement saying hey if a user exists do something if a user doesn't exist do something else and so if a user exists we want to give someone access to a logout button for example and if a user doesn't exist okay we want to give them access to the two links we have right here for example so let's take these links put them into the react fragment is what that's called right there guys the html brackets that are just completely empty it's called a react fragment and so now we're going to have two links saying hey if a user doesn't exist give them the option to log in and register it would be kind of strange to show login and register to someone already logged in you wouldn't even like expect that on like a regular social media website right and so now we can have a button here and so this button we can say something like log out and i'm going to keep this style text decoration and steal it put it on my button and so we can make a log out button here and so if we go to our code check this out we now have a logout button because we are a user that's signed in for example and it's kind of funny the way we currently have the website we're stuck the only way to get rid of this token might be to restart the application but we're kind of stuck with this token we need to make logout functionality to get rid of it to show you guys the other side of this right which is kind of funny we've we're in token jail so we need to make this logout button actually work and so what we can do is we can go over here and on log out when this button gets clicked we can say on click call this function on logout and what onlogout is going to do is it's going to call the logout function we created in our context we haven't talked about the context in a while so let me explain this more in depth in our context we made this logout for example and i just control clicked on that to get there for example and this logout function is down here and what does it do it removes the token item and then it says dispatch of type logout which goes up here and says hey make our user equal to null because right now our user is equal to this and so if we want to log out we have to make that user equal to null which we can do by calling the logout function here so that's kind of what's happening overall guys so if we go back to the nav bar here we can see that on logout's going to get called when we press the button here and so let's go back to our react application let's refresh so now our logout button should actually call the thing that clears our cache so if we press logout boom look at what happened before we had a object of a certain user that was cached and it was showing hey our backend says that test gmail.com is who they say they are they put in the correct password so we believe it's them and now when we've logged out it's gonna be null and you're like oh no it's no that sucks but what's cool is what's happening in our our front end is now that we are a null object we don't exist we can log in and register again so we can go to login and let's just say we want to you know be tested gmail like why to log me out and so you can go and test the gmail and you can log in again and boom you are now back so you'll see here you have access to your email your token your username all this different type of stuff right and as you'll see there you go and so it's kind of showing you guys that we have a full authentication system here and i'm gonna do one last thing in our home page it's very basic right now okay i understand that but let's go to our navbar.js go to the top here and then copy the auth context and use context so copy auth context and use context and then bring them over to your home page um i copied link in there but we don't need that and then go back to your navbar and copy the line where you you do the use context here so then in your home page you can bring this line where we actually use the context and we can do a ternary operator here and so we can say if user exists do something if it doesn't exist do something else and so i'm just going to make the same basic syntax i always make with these ternary operators and so in here i'm going to say this full return statement has to be wrapped in something so we can do another react fragment on the outside so i'm going to say this is the home page so in this like else statement on the bottom here i can make a paragraph and say there is no user data but in this one up here that means there actually is user data and so we can look at the properties of our user and so we can show the user.email for example because that's a property of our user and so we can go in here and say user.email is logged in and let's make this like an h2 just so it's absolutely massive so we don't miss it there we go and so now we can go back and look at this now it's going to say test gmail.com is logged in if we log out it's going to say there is no user data and so this is kind of the full idea of the authentication system if someone's logged in with a test at gmail email they should be able to do all the different things for that specific account so if you're creating a website on top of this code you know that if you have a token that got validated saying that this person was logged in you're going to trust that your password system actually works and you're not like getting hacked yet right and you're going to trust that okay they can do the actions for test gmail.com if i was making a to-do list and i wanted to do like update to do for example then test gmail.com could do those types of things let's say i want to make someone an admin you can store that in your user code as well you can say like you know is this person an admin what type of responsibilities do they have and so all these different types of things kind of tie into this authentication system all right so i'll just show it working again i guess but you know this is kind of the full system is it's all working it's all using apollo server and it's using all these different cool stuff and yeah it's it's a great example of showing how apollo server and graphql can work super well with react to make things kind of simple in the front end hopefully this video was enjoyable i know this is a super long video but it's one of those things where you involve the mutation stuff you involve the creation of components the time really adds up and so if you got to the end of video i would appreciate if you subscribed i'm making more full projects like actual full like create read update delete type projects and so if you're interested in like more full projects that maybe build on top of this authentication system for example make sure to subscribe and i'm going to be releasing more content in the future so thanks for watching
Info
Channel: Cooper Codes
Views: 14,701
Rating: undefined out of 5
Keywords:
Id: 0Z68AHS011Y
Channel Id: undefined
Length: 67min 20sec (4040 seconds)
Published: Sat Feb 12 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.