Next.js and Django Fullstack Airbnb Clone - Part 4 - React, Tailwind, Django Rest Framework and more

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
okay so I want to improve a little bit on how we get things from the API so I want to create a simple service file that you're going to use for example in the properties but you're also going to use them for the login sign up Etc this will make it much easier to set a global URL asimilar so let's begin by going to visual studio code and I can just close everything here and then I find front end folder and inside app folder I create a new folder called services and then in here create a new file called API service do Ts for typescript this is not going to include jsx or HTML so we just have TS because you're not going to include any markip in this file and then we begin by creating a function const API service this equals like that and then we can also just export it so export default API service so now this file can be imported into other files and use this function here so we can begin by creating a get function that we're going to use to get things from the server so get this is then the name of the function you could call it whatever you want uh I want this to be an asynchronous function and function and in here we want to pass in a URL which should be a type of string and we want this to be a promise meaning that we are waiting for something to happen like we get an answer from the server and similar before we continue and either resolve the data or reject it if there are any errors and the promise can be any we can just console log get URL just so that we can see that this is actually working we can import this into uh page. TSX sorry that's not correct into the properties property list so inside property property list so we want to sort of move all of this code into here so that this file can be um much simpler to you uh read and also the code is more reusable so then inside here you can say import the API service hit enter Then This Will import and I think if I go down here where we say get properties let me just test this here API service. getet hello so now this will use this function or class to call this method which is this one which right now will just print out something in the console let's see if it works if I refresh you can see get hello great because we print get and then hello which we Post in from here which means that now it's working but we need much more before this can actually be used and the console can just be there so it's easier to follow and see if there are any mistakes but we can here say return new promise so you can see here this is what we put in to the function and this is what we are expecting to get out of this function so now we want to return the promise and I will say resolve and reject these are two possible outcomes of this create an arrow function like that and then in here we want to use the fetch method so fetch now we pass in the back Tex and we say process. env. next oops next public API host we're going to set this soon but right now you just have to know that this is the URL for the back end which you're going to set in a environmental file and then behind this um curly bra we pass in the URL that we got up there URL and then we can end the back tick like that and then we want to set up what method we're going to use so method this is get since we want to get stuff from this server and then we can set up the headers and this can here first be accept and we're going to accept application SL Json so this is what we want to get and what content type which is also application SL Json um then we have the headers the fetch is finished or whatever you want to call it and when it is finished we say dot then response error function response. Json so we just um convert it to Json and pass it along to the next do then then we get Json data here create an error function now we can say console log response so we know what we got from the server and what we want to print oops here is Jason and then to pass this into the property list for example we can say resolve and just push in Jason so now this promise here is resolved because it was working but if there are an error we can say do catch uh error Arrow function and then instead of saying res we say reject so then we just pushing the error into the property list save so I guess this is not working as it should now by the way the back end is running as you can see here but I don't get any output right now um but if I refresh it still say that but now I get some errors from because you can see the URL is trying to use is Local Host 3000 which is the one we are on now that is because this is not defined yet and we are also try to using undefined hello which is also uh incorrect so let's try to um fix this now and to set up this we can just create a new file and this should go and this should go outside the app folder so together with for TS config and next config Etc so just right click the Jango BNB and say env. local because now we are in the local environment and then next will automatically find this file so here we can say next public API host equals HTTP col 127 0 01 8,000 or we can say Local Host which is the same so let's save that now try to refresh see if that works no still uses the wrong URL um let me just stop and start in case that is the problem so ready refresh okay so what I did now was actually to just delete the local env. local file create it again write next public API host the URL then it just worked so I'm not sure what happened there but hopefully if you had the same error it will work for you as well anyway and I get a new error it's fail on executing fetch on window because the URL is not correct and that is sort of correct because I'm just posing in hello as URL but if I say slash hello and refresh then you can see it going to the back end and it's a 404 error and that is more correct so let's pass in API /properties instead and then you can see that we actually get correct data from the back end nice so then we can actually remove most of this and just use the API service instead so let me just remove everything here and we can say const URL equals SL API /properties remember slash at the end and then I think I can say const Pro um TMP property is equals API service. getet passing the URL from up here if you don't want to specify a URL you can just do it like this it's a little bit shorter let's put on this a wait so that we wait for this to finish so we wait for this promise to either resolve or reject and when that's done we can say set properties and just pass in TMP properties like that so hopefully if I save now go back and refresh okay properties that map is not a function and why um maybe I should say data yes that's correct so now we are using a API service to get the information about the properties and listing them so that makes this page a little bit easier to read perfect then I can also remove this one so that we just use this use effect here which will load only when the page is loaded so everything is still working nice so that means that now I can go to the to-do list here eraser and set this to done before I continue I just want want to say thanks to all of my patrons if you do want to support me you will find a link in the description below okay so um Next Step then is to implement authentication um before I start working on the authentication itself I want to just add one more method to this API service which is a post functionality because we're going to post the data when we log in the user so here we can say post colon as sync function this is also a URL type of string but here we also expect data which can be any type because we are going to make it possible to pass in form data as well as Json so let's just keep it that Annie for now and we're going to return a promise of any type console let look log post URL data so we can see what we returning to post and to what URL then let's just copy this and this down to there and say post method um we can copy head that is correct I think but there I also want to pause in the body of this data so that we can get the post data in the back end okay so close the Fetch and then we have the same as we do up here so let's just copy this and paste it at the end there so you just go through the Json print it to the screen so you know what has happened and similar and save no think I forgot to close something thing yes you can see here I forgot to close this return correctly there so that is closed but now this is not closed but now it is closed so let's just see that it is working yes perfect um okay so have log in sign up and log out functionality let's try to replace this with sign up and log in because we want to make it possible to create a user before we can log in a user so um when we now click this one and sign up we want to activate this and actually send data to the server okay we already created this model so let's find it here in Visual Studio code open up sign up model TSX we need to do a look of changes for this to work so we already imported use state but we also need a router because we want to make it possible to redirect when the user is uh when the account is created so let's import this use router which is a hook from next so from next SL navigation navigation like that um um you have the mod all we have the sign up custom button we might need to import more things but let's keep it at this for now then at the top here we can initialize this router so const router equals use router so now we can use this and we want to keep track of the email the errors and the passwords using state so here we can say email set email equals use State and this should be just an empty string uh const password one set oops sorry set password one this is also just an empty string let's copy this replace with two and two and we also want an array of strings for the errors so const errors set errors equals use State and we can specify that this is a string array like that and that we should initialize this with an empty array actually we can put this at the end so it has a nice stair like that and then I want to connect these fields here with these up here and to do that you can here after input say on change oops Capital C so on change equals e for event and when this event occurs is a set email to e. target. value which is the field we are in right now so let's copy this for the other two Fields but everyone to say password one of course and here set password two um so I think that if we write something in now this will actually work great I don't think there was were before and we can also Loop through the errors if there are any and only show this if there are any errors and to leave through them we just say errors do map so we map through them we want to extract the error and the index and this index is just the iteration index so it goes from zero to how many numbers of Errors you have create an errow function and then in here we say return create a new parenthesis array close that one that's closed but we can close them down there and in here we can move this HTML so you can see now I get an error because I should have one more Cur bra here which should be stopped down there so curly bra curly bra parenthesis curly brace which is this one and instead of just showing the error like this we can say error which is just a simple string but now we will also get a little error because each of these HTML Fields inside s HTML tags inside a map like this needs to have a unique key so here we can say key then we can do a little bit more advanced and say error underscore pass in the index like that so notice you will for example have error underscore Z if there are just just one error save and now you can see that we don't have any errors now perfect um but I think if I just add something there for testing you can see how it will look like great but we don't want that for default um when we submit this form we can call an action called submit form so action equals submit sign up like that so now get the warning because you cannot find this but that's okay because we haven't created it yet so below all of these variables variables we can create the submit function submit functionality and there we can just const submit sign up equals this is an asynchronous function because we want to wait for the server and similar um yes then I want to create an array of data that we are going to post in to the server so const form data so I call this form data even though we are not using the JavaScript form data element but we are just calling it because I like to call it that uh we want to pass in the email field this is what we're expecting in the back end and this is just pointing up to this which again is connected to this one we want to pass in the password one password one the password two and the password to like that now we can just const response equals await API service and when I hit enter now it was automatically imported up there great and we want to use the post functionality now slash API sl/ register and I think that if I open up the backend code this is something that we added there in the previous part so user account okay it looks like I'm wrong we did not do that yet we have just configured how everything of this are connected okay so I need to set up the URLs before we can test this but let's fix the front end first okay so we are now posting to this address and I get an error now because okay I expected to arguments we have not provided the data yet but the data is what we have up here for form data nice now we can say console log response actually this is something we already print out in the API service so we don't need to do that here but we can say if response. access we are expecting the response to have an access property that we know that everything is okay then we going to call a function called handle login which I will come back to soon and we can say sign up model do close so we close the window we are in and say router router. push so we redirect this to the front page if you don't have the access which is just short for Access token then we can say const TMP errors we create a temporary array string because this is a array of strings equals object do values so we need to uh loop through all of the keys in the response that we have response do map error and this can be any types of error create an error function and the curly Braes now we just say return error so now this should generate a array of Errors based on what we get from the server and we can say set errors um TMP errors so we just set this array here or this state sorry this state to the data to get and show it on the screen there so I think that if I just try to submit this now I will get an error but not the one we are hoping for inspect test sign up mode all uh why is this printing there okay yes I have not um so if I just go back here find the submit button this one instead of calling it like this just remove everything as I submit sign up and save so now we can try this it will definitely not work but at least we get some errors because you can see here the data we are trying to post but this is not found okay so then we need to find it in the back end so if you go back to the back end just close the front end for now find the user account then in here we can create a file called urls.py because most of this already comes built in uh when we installed the authentication packages and similar from all o and use as the simple JWT and similar so let's just set up this URLs file and see if you can make it work so if I go back to visuals to the code I Can Begin by importing a few things that we need so from let me just close this from DJ rest or. JWT import get refresh view this is something that we're going to use to refresh the token and from DJ arrest. sorry registration. views import register view from DJ rest or do views import login view we want log out View and user details view and from Jango which is something I want to import at the top here from Jango URLs import path and we want one more thing from the rest framework to verify a token so from rest underscore framework uncore simple JWT views import token verify view then we can set up the URL patterns which is a list begin with path and pass in register slash and we're going to use the register view dot sore view so we just just reuse the view that comes from there set the name to be rest register um we can also set up the log in and log out we have these part login slash login view. S View name rest login copy this paste and say log log out log out View and rest log out um I will come back to the tokens any minute but we can keep it like this for now then we just need to find the main url. Pi which is in the Django BNB backend folder and here we can say po API slash or and alls beginning with API or should go into to user sorry include user account. URLs so in the front end we are trying to reach the URL called API or register and then API or will match here go into this one match this one and use this view to hopefully register and create a user we can try this now by just hitting submit then I get the bad request expect thing something is wrong let's open up the network usually easier to understand expecting value line one column one no it did not make any sense expecting value line one column one Char one H what are we missing do refresh and test again so everything is fresh at least still the same it might be because if we're going to models we're actually expecting the name I would think that this would give me a different error but let's try to find here where we pass this in the name Stein just to provide a default name sign up again no still get the same error so that's not the problem um okay so what is the actual problem Jason pors sometimes it's just a very Sim simple stupid thing AP sorry API service let's try to remove the head do this one more time okay so that did something else ands supported media type is not what we want okay so let me go back to visual studio code I think that this form here need sorry this form that I needs to be stringified in order for the back end to to understand this so here we pass this into the API service we can say Json with capital letters string IFI and wrap this in curly braces like sorry in parenthesis like that so if we save now let's try this one more time submit yes that's better because now we actually got a correct error message saying that my password was too short try one more time the password is too common try a real password and then I actually got a response with the access token back perfect so if I now find the admin area refresh find email addresses here you can actually see that this user is created nice which means that the signup is sort of working now but if you remember that um somewhere here I did this we need to handle the login because we need to store this information in the cookie and I'm going to use the server action for this so it's not stored in the browser so let's jump right into that so I can close most of these things for now I want to keep the sign up model up for now now but inside the app folder let's create a new folder called lib and in here a new file call actions. TS this needs to set the use server at the top because we only want this to run on the server and not in the browser for security reasons then we can import cookies from next import cookies from next SL headers and just export a sync function handle log in so you want to have a function for handling the log in here and into this function we want to pass in a user ID which is type of string and we want the access token which is also just a string and the refresh token which is also a string string now we create a function out of this and then we want to store each of these in separate cookies it's very easy to set cookies here so it's just cookies function. set and then I like to prepend things that's connected to the session or the authentication session with session user ID now we pass in what we want to store here and that is user ID which we get from here do one of the parameters and then we need to configure this l so HTTP only can set this to true and secure and we only want to secure this if you are in production so this is either true or false to check this we can say process env. node EnV so this automatically checks if this is set to production and if it is then this will be true now we can set how long we want the user to be logged in So Max H 60 with 60 multiply this with 24 and 7 so it's 60 seconds um multiplied with 60 Minutes multiplied with 24 hours multiplied by 7 days which gives one week so one week and the pot where this should be stored can just be slash and then we stop it like that then we can do the same thing for the access token so how long uh sorry this is not how long you're logged in this is just how long we store the user ID in the cookie then we have the access token how long should this be active before we refresh this PA in the user access token and this should only last for 60 minutes so 60 minutes before we need to refresh this from the server and then copy this again do the same thing for the refresh token um so if any user gets this cookie it will only be valid for 60 minutes before it's not usable anymore then we need to set the refresh token pause in refresh token and this can also be for one week so let's copy what we have up here like that so I think that's everything I need there for now we're going to expand on this because we're going to use this and create functions for getting this cookies simil uh very easy and similar but here now we can actually implement this handle login functionality so here we can say handle login so now this was automatically imported we imported hand login it's important that you use these curly braces around this one from App Libs action actions all right then we say hand login then we pass in response. user. PK which is the ID or the primary key response. access which we get from server as you can see there and response. refresh and if I open up this here you can see that we have the access the refresh and the user with the primary key and also the email which is something we get from the server now this should be stored so let's try to create one more user just to see that this is working Stein at hello.com and then a password submit okay I was refreshed so hopefully now this cookie should be stored somewhere and keep us logged in nice so with that I think we can say that we are now successfully making it possible for users to sign up if you have any questions about this code feel free to leave a comment below and as as and I will answer as soon as I can I know that there is a lot to take in with the actions and the API service and similar right now but hopefully when we keep using most of this again and again it will stick better so let's just go back here now as it this to done next I want to tackle the login functionality okay so a lot of the things that we did for the sign up we need to Now do for the login but I want to redo that because it's important that you understand everything here so let's find components modules and and login model we have the model already but we need to do some changes also want to have the router here so import use router from next SL navigation like that and we can import the API service so import API service and I think that's it now we need to import the handle login as well so import handle log um and by the way if you don't didn't understand it when we created the user we also logged him automatically in but we want to use the same functionality here to create the login functionality so basically we are logged in here now we just don't see it anyway but we're going to get to that when we are finished with this login functionality um so here I also want a few States but we can begin by setting up the router so const router equals use router and you can set up the state for the email const email set email equals use State can be an amp string and we do the same thing for the password password and set password we don't have password one and password two since this is just the login and then we have the error as well so let me just copy this one and paste it below there so that's makes easier to keep track of the errors and if I scroll down we can connect these to the states so just like we did here we we have this on change paste it email paste it for the password just replace this with set password then we can do the same thing with the errors so let's copy this remember everything paste it like that and we can activate this button here to be submit um form wasn't that what we call it submit sign up okay we can call this submit login and the same for this form should also have an action which should go to this one so action equals paste in submit log in so we get the warning now because this isn't created but that's what we're going to do next so const submit login equals a sync function like that and here we can begin by setting up a form data as well so const form data equals we want to send email to the back end we want to send a password to the back end like that now we set up a const response again equals await API service. poost and we want to post to SL API sl/ login if if you remember that we imported it here the login URL which comes from djr rest authentication framework and we want to say Json do uh string IFI form data and then we will get the response and we can see if um we have the access token asimar just like we did here so I think that I can copy this one paste it just replace this with the login model because that's the one we want to close and then we set the hand login and we return us to the front page else then we want to print or add the errors to this list and this is a little bit different than we did here here we can just say set errors because here we actually get a list of errors response do non field errors and save so I think it actually that is it so let's try to open up this try to log in with something that you know doesn't work unable to log in with provided credentials okay Stein at load but that did work nice so first it didn't work then I TR again it was done working so now I'm essentially logged in but it's import uh it's impossible to know up here if you are logged in or not but let's tackle that for the log out task now we can set this to done and jump right into logging out and to create this I want to create a uh functional component just for this log out button which can talk to the back end so inside this component folder let's create one file called logout button. TSX and make sure that this is a client component I want to use the router here because when we are logged out I want to redirect this back to the front page so import use router and as can sorry as you can see here we can see that we can import this from multiple places but we want to use the next navigation which is the correct one and then we can import a function we haven't created yet reset reset all wor cookies which we need to create soon from do/ li/ actions which is the file we created previously and import menual link which is the links that we are using for these two we want to reuse that for this one then we can create this const logout button equals const log out button colon react. FC for functional component and create the arrow function like that in here we can say const router equals use router so this is initialized and then I want to have a function for submitting the log out to the back end so const submit log out equals sync create the arrow function and just say reset what cookies so we call this function which are going to create soon and then just router oops router. push slash so we are pushed to the front end sorry the front page property push does not exist uh sorry for got the parenthesis like that now is a return so we can print HTML you want the menu link this have a label label called log out and onclick function and when you click this which is want to call this one I can just close menual link and we can save now which will not crash anything because we just created a new file but let's try to use this up in the user menu so find user nav scroll to the top and import log out button you can see that this actually doesn't even work because um there is error in here so typescript doesn't let us use this part right yet um but I think I can say dot dot slash and then log out button this should be printed down here somewhere which I will come back to soon but let's fix this so the error is gone so let's find the file called actions. TS let's create one more server action export a sync and then reset all Cookie cies which is the name that we Tred to use here reset what cookies and this should not accept anything so let's just keep this empty like that and we can say cookies do set sorry cookies with this function call do set session user ID and this can be set to empty um sorry forgot to say function there nice so now we need to reset all of these three cookies so if we just copy this paste paste copy paste copy paste then we can reset the cookies the error there is gone the means that this should now work and then we just need to do a little change to the navigation because now we want to only show this login button and sign up button if we are not logged in so that means that we need to get the user ID so how do we get this user ID I don't want to get is declared but its value is never read okay I haven't shown it down here yet but if I just say log out button that error will move away has no default export sorry export default log out button I forgot to add that no errors and if I click here now you can see the log out button but when we are logged in I don't want to show these two you need to do a little change in order for this to work and the first thing is to create one more action here because I want to make a Bible or make it easier to get this user ID and as you can see here when we log out we set this to be empty which means that if we try to get it we'll only get the empty result which means that we know we know very easy that it is that you are logged out so get data because everything up here we are setting the data so export a sync function called get user ID and here we can just const user ID equals cookies remember this do getet session um user ID user ID like that do value so this will crash if there are no value that's why we're adding this here because then it is sort of optional and this will just return undefined or null so now we can say return user ID if it is there then say user ID or no like that so now it's very secure and this will not crash so I don't want to get the user ID here because I know that in the user navigation we're going to use them multiple places and that's also the case for the nav bar and know that you're going to use the user ID here multiple places that's why I want to get the user ID here and instead just POS it in like a property so here we can import this user ID functionality import get user ID remember the curly Braes and at the top here I can say const user ID equals await get user ID so now this uh sorry need to set this to be an asynchronous function and now this user ID will be available here and we can po them in as properties to these components down here which is what we are going to do so here we can try to pause it in user ID equals user ID then we get a warning from typescript because it doesn't expect something or doesn't expect anything actually and then in the user navigation bar we want to set up this to accept getting these so we need to create the in interface for the properties interface usern nav props craes and here we want the user ID set this as a question mark in case you're not logged in then this is just optional string or null so this can either be a string or it can be null and then we need to make sure that this is a functional component from react so colon react. FC pass in the usern na properties and inside this curly sorry inside this parenthesis we pass in user ID which now makes it possible to use them down here and this might seem a little bit Overkill and complicated but um what this does is that now you can see here this error is gone and then we know that since typescript will check that everything is allowed and secure and similar then this code will not crash now because we only pass in what you are expected to pass in and similar so then we just need to do the same thing for the log out button so now that we have the user ID here we can check down here if we have the user ID or not so Above This menu link here with the login and sign up we say user ID question mark if we have the user ID then we don't want to show these two here we only want to show the log out button so let's paste that in there else and just say colon add the parenthesis again fix the indentation close the parenthesis and close the curly brace from up there you can see here we get the warning now let's see if it makes any sense jsx expression must just have one parent element here we have one two element so let's wrap this in a simple fragment like that and close this could be a div if you wanted to but I like these empty fragments because they are actually not g generating in HTML so if I save now go back click this one we only see the log out button if I click that nothing happened attempted import does not let's refresh just to see there are no errors connected to this one log out nothing happens okay log out button log out button console log submit BL oops let's just see if we are actually clicking this yes reset all cookies why is this not working as it should I can close a little bit here just to make it easier console log refresh okay so if I now click log out we have this one which comes from log out button this should be printed here because this is a server action session user ID you can see that this is being reset so why do we not experience sorry why is it showing up still here that user ID exist console log user ID user ID let's see what this has sort of value refresh nothing there and the value there is null so why is this check here not working on the user nav this one why is this triggering true because the user ID should be null console logf user ID let's see what it says here it says null so if this not equals null I don't think that should be necessary okay what sort of weird stuff is this if user ID then we should be able to log out but there is no user ID oops that's not good because there are more than one user ID if you meant to R Collection children user ID so what have I done wrong I think I just forgot to add curly braces in there saved this now and now we have the login sign up log in again so if I click up here now we see the log out button and the log in button is gone nice so that means that if I go back here now is at this to done and this turn on and now we have successfully implemented authentication to our project and that was it for this time if you have any questions about today's code feel free to leave a comment below and I'll answer as soon as I can see you in the next video
Info
Channel: Code With Stein
Views: 3,152
Rating: undefined out of 5
Keywords: code with stein, django, learn django, django tutorial
Id: hjoJUinu5-k
Channel Id: undefined
Length: 58min 7sec (3487 seconds)
Published: Mon Mar 04 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.