Build and Deploy a Full Stack MERN Social Media App with Auth, Pagination, Comments | MERN Course

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi there and welcome to the ultimate course that'll transform you into a master of the mern stack capable of building real industry projects in this video you'll build and deploy a full stack social media application with complete email and google authentication called memories with pagination search and filtering capabilities details pages authentication comments and much more the memories app is the best fully responsive mern social media application that you can currently find on youtube alongside this video i've also prepared a complete mirn roadmap and a cheat sheet that covers everything you need to become a fantastic man developer the guide includes an entire step-by-step mern mastery roadmap prerequisites helpful illustrations and even mern project ideas that you can build deploy and put on your portfolio to get a job you can download the ultimate guide and use it as a reference on your development journey whenever you're unsure what to learn next the link to the comprehensive guide is going to be in the description i'd strongly recommend downloading it now and referring to it while watching the video especially if you're unsure why are we using the particular technology this video paired with the guide contains absolutely everything you need to become a professional mirn developer this app is a full-fledged crud application which means that if you learn how to build this you'll be able to make the most complex and most modern applications out there if you think about it every app is a crud app in a way crud stands for create read update and delete you can find this pattern everywhere building a blog create posts read them and delete them building a social media network with users create users update user profiles and delete users building a movie application well add your favorites rate them and delete them you get the point the concept of crud is explained in more detail inside of the full marin guide that is linked below this video at the end of the guide you'll also find the best crud projects so if you haven't already now is the time to get your own guide [Music] before we start building out our project let's first get the hosting for the react side of our marin application and more importantly the domain name for our new site or any site you'll create in the future hostinger is my personal recommendation and right now they're offering crazy deals so i simply needed to show this to you currently they're offering a completely free domain name and a lifetime ssl certificate for 3 bucks a month so if we scroll down a bit you can see that they offer great price to quality ratio high speed servers free ssl certificate and 24 7 tech support with that said since i've partnered with hostinger they decided to give you an even bigger discount you can find the link and the discount code in the description enjoy once you visit the link in the description we can simply click get started and finally select a web hosting plan as you can see we have a 30 day money back guarantee and now we have to choose a period of our hosting in my case i'm going to choose 48 months as that's going to provide us with the cheapest price we can scroll down a bit to create our account and finally after you select your payment method you can enter a coupon code right here that's going to be javascript mastery all caps no spaces when you apply that you're going to get an even bigger discount with that said let's go ahead and purchase it and i'll see you straight inside of hostinger's dashboard as you can see i'm personally using hostinger for my brand for all of my websites and most importantly i'm using their domain names and hosting for the upcoming js mastery pro course by the way which domain name do you prefer jsmasterypro.com or simply js mastery dot pro let me know in the comments down below with that said if you purchase the premium shared hosting then you should see a claim your free domain button right here in my case i'm going to click claim domain and i'm going to do something like js mastery or just jsm and then dash mern of course you don't have to do this right now you can choose the domain name after you build your application so i'm just gonna check availability and it is completely available you can see we have it for free and you can click the claim domain button right here to finish your process and in just a few seconds our domain is going to be registered and then we'll be able to deploy our client-side application straight to hostinger's hosting and that's it in just a few seconds we purchased the domain name and set it up at the end of the video we're going to deploy our application to hostinger so what exactly can you do in our memories application as the name suggests it is an album of memories where people from all around the world can add the most notable places they visited or the wildest things they've done let's take a look at all the features of this memories application one of the main features is pagination which allows you to only fetch a certain number of memories at a time then we have the complete search and filtering functionality we can search for a tag like europe or search for a part of the title with something like the and get all the matching memories our application will also include client-side routing a memory details page you can click on a memory to get more information about it as you can see we'll even implement the recommended memory section so let's check out a few places we have the coliseum we also have the prague castle these don't necessarily have to be memories or places you have a fully functioning crud mern application and you can turn it into any topic you'd like make it completely your own auth or authentication is a complex process and therefore it is another essential part of our application we are going to allow our users to log in and register here a user can create a real account in the database sign in with that account or sign in using google automatically while building the authentication you'll thoroughly learn every step of the way we'll use json web tokens or jwts for short and google oauth finally we're going to add the comments and most importantly refactor the entire user interface and make our app completely mobile responsive no worries at all if you haven't worked with the marin stack before or you don't know what the heck mirn is let me give you a quick introduction mern stack is a javascript stack used for easier and faster deployment of full stack web applications the letter m in mern stands for mongodb a nosql database in which data is stored in documents that consists of key value pairs similar to json javascript object notation the letter e stands for express which helps us build the back end quickly while staying in the javascript ecosystem the letter r is of course for react almost all modern tech companies from early stage startups to the biggest tech companies like microsoft and facebook use react you learn react functional components and their reusability react file and folder structure and more importantly the use of redux state management library and finally the letter n is for node.js the runtime environment that allows you to write back-end code using javascript ultimately saving you the trouble of learning a new programming language capable of running the back end on top of all of that you'll also learn how to deploy your websites so that you can share them with your friends or potential employers put them on your portfolio and get a job once again downloading the complete mirn roadmap is crucial here so now is the time to go down in the description and get yours if you haven't already and just before we dive straight into the code if you'd like me to make another marin course leave a like comment and subscribe if this video reaches 20 000 likes i'm recording another complete maran application with that said without any further ado let's dive straight into the code first we're going to open an empty visual studio code window you can use any code editor but i prefer visual studio code for many benefits that it has secondly we are going to go to your desktop and then create a new folder you can name it memories project now you have to drag and drop it to your visual studio code once we're in you can go above and then click view and terminal this is going to open your terminal and since we'll be working technically with two different applications here we're going to split our terminal into two parts first one is going to be for our client side application or react side and the second one is going to be for node we are going to create two separate folders as well first one is going to be named client and the second one is going to be called server now we can cd into client with our first terminal on the left side and there we are going to initialize an empty react application by typing mpx create react app dot slash make sure you're in the client directory in terms of prerequisites the only thing you're going to need is going to be the newest version of node just click the newest one and download it for your own operating system while the client side is installing we can create a new file called index.js inside of the server directory this is going to be the starting point of our server application inside of the second terminal we're going to navigate to that server directory and there we're going to run the command mpm init minus y this is going to initialize an empty package.json and now we'll be able to install all the necessary dependencies dependencies that we need are going to be as follows npm install and we need body parser this one is going to enable us to send post requests then we need course which is going to enable cross origin requests then we need express of course we're going to use express as a framework for creating the routing of our application and then finally mongoose we're going to use mongoose to create models for our posts and then finally we need nodemon we're going to use nodemon so that we don't have to manually reset the server every time we make a change instead nodemon will be doing that for us you can click enter and this should install all of the necessary dependencies while that is installing we can go into index.js and import these dependencies first of all we have import express from express then we have import body parser from body minus parser import mongoose from mongoose and finally import course from course just like that now you might be confused if you worked it back in so far you know that the usual syntax looks like this const express is equal to require express thankfully in newest versions of node we can use the import syntax which is a lot more modern and a lot easier to use the only thing we have to do to enable it is that we have to go into package.json and there we need to add one line below the main index.js in here we have to say type make sure everything is in double quotes strings so type is equal to module and then add a comma that's it while we are here we are also going to delete this test script and add a start script so start is equal to nodemon index.js now you can close your package.json index.js and wait until our client side is initialized then we'll be able to install all the necessary dependencies for the client side as well react application is initialized let's take a look at what dependencies are we going to need to make sure we have the same versions of the dependencies installed i'm going to provide you with a full package.json file you can open up your package.json scroll down to the description find the client-side package.json file and then simply paste it over the existing one that way we're making sure that everything 100 works because we're going to have the same versions of specific dependencies after you're done pasting it simply type npm install dash dash legacy dash peer dash depths like this and make sure that you're in the client side directory simply press enter this is making sure the code you see in the video produces the exact same outcome for you even if you're watching the video a few years after it has been released later in the video you may see me install a few more dependencies once again things like material ui jwt decode and many other things but since now you've copied the package.json run the installation command you won't have to reinstall any dependencies later on in the video definitely not for the client side so just keep that in mind you already have all of the necessary dependencies for the client side development while that is installing we can go ahead and check what we have in our client folder inside of here we have an src folder with a lot of things inside of it we are not going to use all of these things so i usually like to just delete the whole src folder and create a new one after you do that there's only one thing that we absolutely must have in our react application and that is the index.js file so you can go ahead and create that index.js this is the file where we're going to connect our react application to index.html file so import react from react import react dom from react minus dom and then also import app from dot slash app we don't yet have this component but we're gonna add it soon and then we have react dom dot render the first thing is the app component and then the second thing is document dot get element by id and then we have to specify the string of root with this line we're connecting to the div with an id of root great now we have to create that app.js file app.js and there we're going to have a simple functional component so import react from react const app is equal to a functional component and there we're going to have a return for now let's just create a div and inside of that div we're going to have an h1 which is going to say app and of course we have to do export default app with this we should be ready to run our client side let's save it and let's save the index as well to run the application we just simply have to say npm start that's it great we can see our app here and if we go back you can see compiled successfully for now we're going to close this terminal by typing control c we did that for a reason that first we're going to set up our back end we have more stuff that we need to set up there we need to connect to the database create a mongodb cluster set up the models and also create some documents so first of all we're going to close our client all together and collapse this and then finally just go into the index.js of server that's where we're going to spend the first part of this video in inside of here what you need to do with every express application is first initialize this app so app is going to be equal to express and then you simply run it as a function now we can use all different methods on that app instance first let's do some general setup we're going to say app.use and then inside of there we're going to say body parser dot json and now in here we have to do limit is equal to 30 megabytes i just did that because we're going to be sending some images which can be large in size and then we're going to say extended is equal to true just like that now you can copy that line paste it below and we are also going to do body parser dot url encoded and put the same thing as parameters we are just setting up the body parser so that we can properly send our requests now we're also going to use that course so we're going to say app.use and just put course in there and call it as a function that's it now is the time to connect our server application with a real database for that we're going to use mongodb more specifically their cloud atlas version of mongodb which means that they're going to host our database on their cloud we can go there the website is mongodb.com cloud atlas the link is going to be in the description and then in here you can click start free and then just create a free account which is going to enable you to create something known as a cluster that's going to act as our online cloud database once you do that you'll be greeted with a website that looks like this you can just go ahead and click build a cluster then you can choose share clusters which is going to be completely free and then you can just click create cluster at the bottom of the page that's going to start the deployment of our cluster it can take one to three minutes but while that is deploying let's do some setup you can go in here to database access and then you can click add a new database user in here you can create your own username and password i'm going to use javascript mastery and then password cannot be simply one two three one two three so i'm gonna use javascript mastery and then one two three just like this now i can click add user with this credentials we'll be able to read and write to any database great finally we need to go to network access and then in here you can click add ip address once you do that you can click add current ip address and click confirm that's it now we go back to clusters and wait until our cluster is deployed now you can click the connect button right here that's going to ask us if we want to connect it with a shell our own application or mongodb compass which is a graphical user interface for looking at our databases data we can click connect your application because we want to connect it to our server side express and node application you can copy this string and then we're going to go back to visual studio code inside of here i'm going to create a new variable which is going to be called connection url all uppercase and then in here you can create a string and simply paste the whole thing that we received right there from our mongodb atlas in here you can enter your username and password make sure to delete these arrows as well so mine was javascript mastery and then the password was javascriptmastery123 you can enter your own credentials that's it of course in real applications your credentials should be secured so we cannot simply put them in here later on in our video before the deployment of the whole application we're going to create environmental variables and then we're going to store that connection url right there the second thing we need is going to be port so const port is equal to process dot env that port for now we're going to use the 5000 but later on once we push this to heroku heroku is automatically going to populate environmental variable called port finally we use our mongoose to connect to our database mongoose.connect it is a function that accepts two different parameters first one is going to be the connection url and the second one is an object with all the options we're going to use two different options first one is going to be use new url parser which we're going to set up to true and the second one is going to be use unified topology which we are also going to set up to true these are not required but if you don't set them up we're going to get some errors in the console or rather warnings so let's just have it for simplicity purposes now we're not going to end this sentence right there we're going to chain a dot then because this returns a promise so in here we're going to have a dot then and also we're going to have a dot catch just below now what do we want to do if our connection is successful well then we want to call our app and then on it we want to do app.listen listen accepts two parameters the first one is the port which we just created right there and the second one is a callback function which is going to be ran once our application successfully listens that's going to be a simple console log which is going to be template string and it's going to say server running on port and now we can use template strings to say port this needs to be all capitalized that's going to say server running on port 5000 great and finally if the connection to the database is not successful we're going to have an error there and we are simply going to kansa log error dot message that's it and the final piece of setup is going to be mongoose.set in there we're going to set use find and modify to false so just pass the second parameter false this again makes sure that we don't get any warnings in the console that's it now if we go back to our package.json we specify the script start and let's run it you can go ahead and type mpm start that's going to run at nodemon index.js and we should get a console.log saying server running on port 5000 that's it our server is successfully connected to the database and now that we are connected to the database we can start creating routes for our backend application to do that we are going to create a new folder inside of the server which is going to be called routes inside of the routes we are going to create a file called posts.js inside of there we're going to add all the routes that have to do something with posts both being that cars that you saw previously to do that we have to import express from express and we also have to set up our router constructor is equal to express dot router with a capital r now we can start adding our routes our first route is going to be router.get the path is just going to be slash and then in here we can specify a callback function that is going to be executed once someone visits localhost 5000 slash great in here we're always going to have request and response it's going to be the same thing for every single callback function inside of our router.get the second parameter is going to be a callback function that is going to be executed once user visits this route instead of every callback function we have request and a response for now let's just do response.send and then in there let's say this works that's it now we have to export the whole router so we're going to do export default router just like that and now we can go ahead in index.js and import that router which we just exported from there to do that we have to do import post routes from dot slash routes slash posts.js now we can use express middleware to connect this to our application to do that we have to type app.use and then for the first parameter set up the starting pad for all the routes inside of the post.js and that thing is going to be posts and in here we set the routes so what this did is it said that every route inside of the post routes is going to start with posts that means that this route inside of posts is not reached by going to localhost 5000 and then slash it's reached by going to localhost 5000 and then slash posts because we added a prefix of posts to all routes in here now let's see if we can get this response inside of the browser to do that we have to go to this url localhost 5000 slash posts i'm going to copy it go back and then check it in the browser as you can see at the top left corner we get this works which means that we successfully connected our express application and we are running it on localhost 5000 great before we move any further with the functionality we are going to set up an amazing folder structure for all the backend applications that's going to make them much more scalable to do that we are going to create a new folder called controllers inside of the controllers folder we are also going to create a file called posts.js inside of there we're going to create all the handlers for our routes what does that mean well let me put it side by side inside of here we don't want to have some logic because if we keep adding routes and adding more complex logic like this our file for routes is gonna get long and we're gonna get lost between all the logic and all the requests and at the end it's going to be hard to see what routes do you even have access to to simplify that we can do something like this we can extract all the functions or all the logic from the routes and then take it right here in the posts of the controllers inside of here we're going to declare that function for the router.get let's give it a name const getposts is equal to that same callback function which we just copied of course so that we can use it in post.js we have to first export it right there export const get posts great now we can go back into our post.js and then there we can import all different functions for now we have only one that's going to look like this import and now inside of curly braces considering we're doing named and not default export in there we can name that function get posts from dot dot slash controllers slash posts that's it now the only thing you have to do is simply say router.get and then we execute a function called getposts in here don't forget to add posts.js in react we don't need to do that but in node we absolutely have to at this point i don't think you can see the purpose of having the controllers and routes separate which is completely fine but as we keep adding more routes you're gonna see how clean this is gonna look like we'll be able to see all the routes just like this and then execute all the functions in the other file great with that said let's create a new model for our post we're going to create a new folder called models and then inside of there we're going to create a file called post message.js inside of there we're going to utilize the possibilities of mongoose to do that we have to say import mongoose from mongoose now first we have to create a mongoose schema const post schema is equal to mongoose.schema and that's going to be a function which is going to have an object immediately in there that's it well what is a schema with mongodb you can create documents that look absolutely different one can have the title and the message what can only have the message and so on mongoose allows us to give some sort of uniformity to our documents we are going to specify that each post is going to have to have these things so in here each post is going to have a title which is going to be of a type string each post is also going to have a message which is going to be a string it's going to have a creator which is going to be also of type string we're going to have some tags which is going to be an array of strings so that that's why we put an array sign there we're going to have a selected file which is also going to be a string we're going to convert an image into a string using that base64 then it's also going to have a like count this time we're not going to simply say a number we're going to say an object and then inside type is equal to a number because we have to add additional information and that additional information is that by default we want to set it to zero and finally we're going to have a created add property which is going to be an object again of type date and also it's going to have a default value of new date just like this make sure to call it and write it exactly like this now that we have a schema we have to turn it into a model to do that we're going to say const post message is going to be equal to mongoose.model and then in there we'll do post message make sure to do the same thing here exactly like this post message or you can call it anything you'd like and then the second parameter is going to be post schema that's it now we can do export default post message we are exporting a mongoose model from the post message file and then on that model later on we'll be able to run commands such as find create delete and update great now that our model is done we can start adding more routes inside of here i'm going to copy the line this route is going to be router.post and once we go to that route we're going to run the create post function which we are also going to import from the controllers so in here create post now we have to save it and go to the controllers in here we're going to say export const create post it's also going to be an error function which has a request and response and then in there for now let's do res that send post creation now is the time that we have to start implementing real logic for getting posts and for creating a post to do that we are going to import post message with a capital p from dot slash models and postmessage.js this gives us access to a real model what can we do with that well first of all each callback function is going to have a try and catch block it looks like this try opening and closing curly brace and then the catch with an error inside the code in the catch is gonna happen if we get an error right there and the code in the try is gonna happen if everything is successful so in here let's try to retrieve all the posts that we currently have in the database const post messages is equal to post message dot find just like that now this wouldn't be correct because post message that find or finding something inside of a model takes time which means that it is an asynchronous action for that reason we have to add a weight in front of it and therefore we have to make this function asynchronous after that we can console.log our post messages and finally we need to make our function return something so if everything works then we're going to say res does status of 200 which means everything went okay and then we're going to return json which is going to simply be an array of all messages that we have we don't even have to cons log it we're just returning it that's it we also have to respond with something if there's an error so we're going to say rest that status and then in here let's do 404 and then dot json and we're going to return message to be equal to error dot message just like that now this is it for our get posts and how can we see if it works well our server is already running on localhost 5000 so let's go check it out and that's it you can see that we have an empty array this is not that interesting right we just have an empty array now we have to implement the logic for adding different posts and we're going to do that right here to create a post we're also going to do a try and catch block with post requests you have access to something known as a request that body so we're going to say body is equal to wreck that body and we won't be able to cancel like this right now for the reason that we don't have a way to send post requests yet that's the exact reason why immediately after we create this create post we're going to move on to the front-end side to create a form and basic layout for making different posts our request that body is actually going to be our post so we can name it like so and then we need to create a new post we do that by typing const new post is equal to new post message we call it and then in there we pass that values that we're receiving to the request that body yet we are not sending them but we're going to do that once we implement the logic on the front end then in the try block we're going to say new post dot save this is again an asynchronous action which means that we have to add a weight in front of it and also async on the whole function once that is saved we're going to respond with resda status 201 which means successful creation and then that json we're just going to send that new post in that's it if it's not successful we do res dot status and then 409 that's json and then in there we do message is equal to error dot message you can learn more about this http codes right there under the following link it's going to be in the description but generally it looks like this all requests that starts with 200 are successful 300s are redirections 400 are client errors and 500 are server errors you can take a look for example you can read only those with stars these are the most important ones and then see what each one says in here 200 is the most popular one the request has succeeded great the link is going to be in the description now we have our create post function completely done and now is the time that we focus more on client and implement the logic for actually sending or creating posts moving to the client side we are now going to create a whole skeleton for the front-end application there is one thing that i forgot to tell you to install at the beginning and that is npm install add material minus ui and then forward slash core this is going to be the ui kit we'll be using material ui is really popular when working with react because it allows you to create nice looking applications without a lot of styling while that is installing let's create our components folder inside of there we're going to have two folders one is going to be called posts and the other one is going to be called form inside of the form we're going to create a form.js file which is going to be our form component inside of the posts we're going to create posts.js file which is going to be the component for the posts each one of these is also going to have its own styles.js we'll be using materials ui way of styling yeah it's css and js but it's it's not that awful you're going to see it soon and then again styles.js in the posts that's why we have folders the last thing we have to do is create one more folder which is going to be inside of the posts folder and that name is going to be post inside of there we are also going to create just one thing which is going to be post.js file and also styles.js this is the folder structure that works really well in medium to large level applications you can see everything is nicely put inside of the folders we have the styles there and if only one component uses some other component like only posts uses post then that post component is going to be inside of there maybe it doesn't make a lot of sense right now because we just added a lot of files but not a lot of code but it's going to make more sense once we actually start writing code great now that we have the structure of our application let's actually start with app.js first of all i'm going to run the application again by typing npm start and now we can use material ui components so first of all at the top i'm going to import all the components we're going to use in this app.js file all components start with the capital letter and these are going to be container app bar typography grow and grid and we're going to import them from add material ui and then forward slash core great inside of here let's start with basic structure i'm going to delete this div and create a container that's going to make sure to just center everything inside of there i'm going to put the property called max with equal to lg which is large and then inside of there first thing that we have is going to be the app bar app bar is going to have a position of static and also a color of inherit inside of the app bar we are going to have a typography typography in material ui basically stands for any textual element like h2 paragraphs or really anything but it gives it a nice looking font so in there we can see variant is going to be equal to h2 and we are also going to have a line equal to center in there we can put the title of our application in our case that's going to be memories and this is supposed to be variant just like that and then we're going to have our image so image in there we're going to have an src which is going to say memories alt can be memories and then we can put the height to be equal to 60. we don't need it to be more than 60. now we don't have this image yet so let's create it i'm going to leave the link to the image down below and then what we can do is you can create a new folder in the src called images and then inside of there you can download and put that image memories.png looks like this just to give some life to our application i misspelled container there as well now we can import that image that's going to be import memories from dot slash images slash memories dot png great now if you save this let's see if it works okay and we have a huge image right there once we add some styles this should look much better before adding the styles let's just finish with the structure below this app bar we're going to have a grow component grow just provides some simple animation grow is going to have a property of n so it's going to grow in and then inside of that grow we're also going to have one more container inside of that container we're going to have a grid component that grid is going to be of a type container it's going to say justify to space between and also align items to stretch and we're also going to give it some spacing which is going to be equal to 3 that's it now inside of that grid which is of type container we can add two different grid items let's do that grid and then item access is going to be 12 which means that it's going to take the full width on extra small devices and on small and medium it's going to be 7 which means that it's going to take 7 out of 12 spaces on small or larger devices great so this is our grid component and then i'm going to copy it and paste it below this one is also going to be extra small 12 but we're going to change the small to b4 inside of this first grid we're going to have our posts component we created the file for it but we didn't yet create or import the component and then just below in here we're going to have our form component now we have to create those components and then import them right there so let's do that let's go into the form and then inside of here we're going to import react from react const form is equal to a normal functional component which is going to return just an h1 that says form for now and then we're going to export default form that's it i'm going to copy all of this now go into the posts file paste it there and then just change the form to say posts and then change this to posts and finally we're going to do the same thing for the singular post component in here i'm going to change posts to simply say post that's it we know our hierarchy our posts is going to use the post component so what we're going to do is we're going to import that post into our posts so right there below the title we need to add a react fragment so we can add multiple things in there below posts we're going to import the post component so import post from dot slash post slash post and now we can create multiple post components just like so let's add two for now great the last thing we have to do is collapse this go into the app and then finally import the components we just exported that's gonna be import posts from dot slash components slash posts and we need to go one level further to slash posts and finally you can copy the line and then change this to form that's it now we are importing the posts and the form as well in here and now we shouldn't get any warnings or errors that we don't have these components here because they are there you can see the app is compiled and running on localhost 3000. let's visit in the browser and see what we have let's be honest this looks pretty bad for now but we're going to keep adding more styles and structure to it firstly let's add styles to our app.js here is how we can properly add styles to a material ui application inside of the src folder we are also going to create a styles.js file in here we need to import make styles from add material ui core and then slash styles make sure to import it not as a default import but as a named import instead of curly braces and then below we do export default we call that make styles and now inside of there we put a callback function which immediately returns an object this video is about creating a mern stack application connecting it to the database connecting the server to the front end and everything else that we still have to do for that reason you're not going to have to type the styles i'm going to leave all the files for the styles down in the description and you'll be able to copy them so let's start with this one you're gonna have these styles make sure to copy these from the description save it and then go back to the app.js in here we have to say import use styles that slash styles and the last thing we have to do is say const classes is equal to use styles and call it just like so so this is going to be the process for all different components again we're just going to copy and paste it and you don't have to worry about styles the only thing you have to do is actually add them in here so let's start with the app bar first in here let's do class name is equal to classes that app bar so the same we called it right here great then we have to add the classes for the image so class name is equal to classes that image and then finally class name is equal to classes dot heading right here and i just noticed that i have a typo here this should be height spelled like so great now if we go back to our application let's see how it looks like as you can see this is much better now let's add the styles for all the other components meaning posts post and the form you can do that by going into these styles styles.js and then just copying the link in the description you should be able to find all the styles right there there we go i copy and pasted all the styles for the form and now going into the post.js i'm gonna copy and paste all the styles for the post.js as well right here that's it and finally styles for the posts plural this time we don't have a lot that's it after you copy and pasted all these styles the last thing that you have to do is copy the same two lines that's this thing here we have to copy the import use styles and we also have to copy cons classes is equal to use styles so you can hold alt or option and then copy this line and then keep copying this line then you can press ctrl c or command c to copy both lines and let's add the same thing to all these files that's going to be import that and then finally drag and drop it here same thing goes for the post inside of here you paste it import goes at the top and then we have cons classes so that we'll be able to use the classes and the last thing is in the posts in here we also have to import the used styles and then finally use that classes great with this all the classes are now imported and then we'll keep adding the jsx and the only thing you'll have to do is say to something for example classname is equal to classes.something that's it we simplified your process there because this video is long enough even without adding the styles we have to focus on things that really matter connecting this to the backend and connecting it to the database now let's start implementing the calls to the api we're going to close this collapse it go to client and then in the client we're going to create a new folder called api inside of the api we're going to have an index.js file and inside of there we're going to import axios from axios we're going to use it to make api calls in here we have to specify our url and that url is going to be a string that's going to say http and then localhost 5000 slash posts as we discussed on the backend side so this is the url pointing to our backend route and now in here we can create a function called fetch posts which is going to be equal to an arrow function that's simply going to make an axios dot get call to our url as you remember localhost 5000 posts simply returns all the posts that we currently have in the database now we're not going to use it in this file but rather we're going to export that function now we have to focus on adding redux capabilities because all actions towards our backend are going to be done using redux we need to dispatch those actions to do that we have to add some boilerplate code meaning we do have to create a few files and folders but later on on bigger applications this is going to be extremely great because of the scalability and i agree to implement redux you have to add a lot of files and folders but it's going to be great in the long run because it makes our application scalable that means that as our application grows we'll be able to use that same old consistency redux offers us without any trouble great so to do that we're first going to create a folder called actions and a folder called reducers inside of actions we're going to create a file called posts.js and we're going to do the same thing for reducers inside of the reducers we are also going to have an index.js file and this also seems like a good starting point now that that is set up we can go to our index.js file and this is the place where we are going to initialize redux what are some of the things that we need well let's start import provider from react redux provider is going to keep track of that store which is that global state and that allows us to access that store from anywhere inside of the app we don't have to be exactly in a parent component or in a child component we can access that state from anywhere then we're going to import create store apply middleware and also compose from redux finally we need to import thunk from redux minus thunk that's it now let's set it up to set redux we first have to create store so that's going to be cons store is equal to create store create store takes in two different things first we have the reducers which we didn't define yet as you can see they are red we need to define the reducers and the second thing is going to be compose which is a function and then in there we put apply middleware and then in there we pass thunk as you can see and looks like i misspelled compose at the top great so the only thing we have to do right now is import reducers we are going to import reducers from dot slash reducers that means that we also have to go ahead in reducers index.js to export them inside of here we're going to use something known as combine reducers from redux and then there we can say export default and call that combine reducers we call it as a function and then put an object inside of it now in here we can use all of the individual reducers that we have in our case we are only going to have posts so for that reason we have to import posts from dot slash posts so we can go to that file and now let's talk about reducers what are reducers well a reducer is a function so let's do it like that const reducer is equal to a function more specifically it is equal to a function that accepts the state and also it accepts the action then based on the action type so if action.type is equal to let's say create then we want to do some logic here more specifically we want to return either action or we want to return the state changed by the action usually you're going to have multiple if statements for a lot of different things and for that reason people prefer to have the switch statement and this is how it works you have the switch statement and then right there as a key you put the action that type as we discussed and now in here we can specify all of our types for example we know that we're going to have a fetch all action for fetching all the posts and let's also do the one for creating so that's going to be create post great in here we are later going to return some logic but since we don't have anything yet let's just return the state and in reducers the state always needs to be equal to something we cannot have it equal to nothing that's why we have to set this initial value our posts are going to be an array and that's why we are specifying this empty array there and also just to simplify things our state is always going to be simply posts because we are in a post reducer so we can rename the state to posts and also as a default return people usually just put return and then posts that's it we're gonna add logic here later on but now we just need to set it up so that it works together once we connect the redux to the store great now you can see that this reducer is currently not being used so what we can do is just export default that function we created we don't actually have to use it here we are using it in here in combine reducers we are importing that posts and then setting posts equal to be posts considering both the key and the value are the same we can only keep the first one that's it we can put this in one line and as you can see our index.js off reducer is done now we are successfully exporting the thing that we previously imported in here in the index.js of the src and now we have this variable in the store now that the store variable is successfully created we can wrap our application with a provider component we're going to do it right here provider and then we wrap our application with it we can do it like so we're going to put the app here and then just move the comma right there people usually like to span it across multiple lines just so it looks simpler to understand and this is it the last thing we have to do is specify the store to be equal to the store we just created right there that's it our application is now successfully using redux and we can start using all of its capabilities looks like we forgot to install one thing which is react redux so just copy that close the terminal by control c and then in there you can type npm install and then react redux once that is done it means that our application is successfully connected to redux now we can start making use of it first we have to dispatch our get posts action and we are going to do that into our app.js so let's go in there in pre-hooks era redux was kind of hard you had to go down here and then do some crazy syntax like this and then map state to props it was crazy now with use of hooks we can use redux much more easily what we can do is import a hook from react redux so import use dispatch from react minus redux what this allows us to do is to dispatch an action okay so how does it work first of all we have to define that dispatch so we need to say const this patch is equal to use dispatch that is a hook now that we have access to this dispatch we need to find a way where we are actually going to dispatch the action and the best way to do that is inside of the use effect use effect is initially going to be just the component that mount but later on it's going to become the component will update so to do that we have to specify the use effect it looks like this we call it and then inside of there we put a callback function and as the second parameter we put an empty array there and finally we can use this dispatch to dispatch an action right now we don't have any actions in here so our next goal is to create an action we can do that right here by importing it import get posts from dot slash actions slash posts you can see it's not currently being used so how do we use it well you just specify the function get posts and then you call it this is our successful dispatch that's it and react is telling us please include the dispatch in here in the dependency array so let's do that great now it's time for us to actually export get posts from the actions let's go there inside of here inside of the post we just have a completely empty file now we have to make use of this index.js file in the api we created not that long ago to do that we're going to do import star as api from dot slash api this import star as means that we import everything from the actions as api that means that we'll be able to use this fetch posts like this api dot fetch posts and we do it this way because we're going to have a lot of calls exported from the api now we have to create actions more specifically action creators action creators are functions that return actions how do they look const get posts is equal to an arrow function and there we can declare an action const action is an object actions must have the type property in this case let's say that we're going to name it fetch all and also they can have some payload and payload is usually the data where we store all of our posts and finally we have to return it return action this is it we successfully created this action creator the problem is we are working with asynchronous data to actually fetch all the posts some time is gonna have to pass and for that we have to use redux tank redux tank allows us to in here specify an additional arrow function bear with me the syntax is crazy but you just have to do this async and then one more set of parentheses and then in there as a property we get access to this patch this is it now we created a function that returns another function and now we can use the async await capabilities of course we have to have another arrow right there great and there is one more difference instead of actually returning the action with redux tank what you have to do is you have to dispatch the action that's it so just to recap let's go back action creators are functions that return an action and an action is just an object that has the type and a payload with redux thunk since we'll be dealing with asynchronous logic we have to add this async dispatch function in front of it and then instead of returning the action we have to dispatch it to actually make this work let's add a few lines we're going to add that try and catch block and then in the try i'm going to try to fetch all the data from the api we can do it like this const we're immediately going to destructure the data and then is equal to await api that fetch posts so what we're doing in here is we are first getting the response from the api and then in the response we always have the data object which we're returning from the back end and then we get the data and basically data represents the posts so what we can do is in here we can remove this action and we can immediately dispatch an action an action is as we said an object which includes the type the type is going to be fetch all and then the payload is going to be data now we are successfully using redux to actually pass or dispatch an action from the data from our back end in here we can simply call the log the error dot message and if you remember we actually imported this action which means that we have to export it so export const get posts that's it as soon as this action gets dispatched and we're doing that from here we immediately go to the post reducer and there we have to handle the logic of fetching all posts considering we are immediately fetching all of our posts in here we are fetching the data from the api and then sending that data through the action.payload we can immediately in the reducer just do this return action dot payload and that action that payload are our actual posts now we've been working a lot with all of this redux data passing but how do we actually retrieve the data from within our components well to do that we are now going to in the component that actually needs the posts and that's going to be post component inside of there we have to somehow fetch the data from that global redux store we can do that with the help of something known as selectors so in there we're going to import use selector from react redux great now that we have that we again initialize it as a hook we're going to say const posts is equal to use selector inside of the use selector we're going to have a callback function as a parameter in that callback function we get access to that whole global redux store or state and then we can immediately return state that posts how do we know that it is called posts well if you go to the reducers index.js you can see in here we have posts that's it now that we're getting these posts what do you say that we just do a simple console log and put them there great now we save this and let's see if any data is showing up open the console refresh and you should be able to see we do get an empty array at first in post 11 but then we get a network error saying access from origin localhost 3000 has been blocked by course policy there is one thing that we need to do in our react applications to make requests to our server work to do that we need to go back into our package.json of the client side and just below this private to true we're going to set a proxy proxy is going to be equal to and now we need to specify our port http localhost and that's going to be 5000. if we now save this whenever you change a package.json file you need to rerun your terminal so i'm gonna close it and then run npm start one more time and let's see if that's gonna fix our issue after i spent some time debugging i found that the thing that we added the proxy that was absolutely necessary but that wasn't the fix to our issue the fix was this little bug right there we specified the routes before we specified app.use course so we need to have the course above the actual app.use routes right there if you now save this and then go back you should see if we refresh that we don't get an error anymore and we just have an empty array at first we have this empty array because that's what we set up right there in the reducer but later on once we make a request then we get the new empty array and that's after the data has been fetched the data has been successfully fetched but still it's an empty array that means that the get request works and now is the time to implement the form so that we can make a post request to our database and actually add new posts let's start by adding the jsx to our form first of all we have to import all the components we're going to use that's going to be text field button typography and paper and all of that is coming from add material ui forward slash core now let's create our form inside of here we are going to create a paper paper is like a div that has whitish background in there we're going to add a class name which is going to be equal to classes.paper remember we imported all the classes so that we don't have to create them now inside of there we're going to have a form form is going to have autocomplete set to off then we can add no validate classname is equal to classes.form and then finally we have the on submit which is going to say handle submit just like that a long line but we have everything that we need and that handle submit is going to be the handler function so we can create it right now handle submit is going to be equal to an error function and then later on we're going to add what we need inside of there great moving on to what we have inside of the form inside of the form first thing that we're going to have is going to be a typography more specifically we're going to use a variant of h6 and then inside of there we can say creating a memory because all our posts are indeed memories below that we are going to have a text field text field is a self-closing tag and then first text field is going to be about who is creating a post so we're going to say name is equal to creator then variant is going to be outlined label is going to be creator with a capital c then what else do we have we're gonna make it a full width so full width just like so and then finally we can add a few more properties that's gonna be value and the on change two of the most important things and this is already getting long so let's space this out in multiple lines variant label full width and then finally the last two are going to be the most important ones and that's going to be value and finally the on change okay great so where are we going to store that value and what is the on change going to do well the value is of course going to be stored in the state more specifically in the state called post data and then dot creator that means that the whole data from our post is going to be stored in the pose data object in the state and then each object key is going to be a specific text field so let's create that state using the use state property in here we're gonna import the use state hook and then right there we're gonna say const post data and then set post data is equal to use state and that's going to be an empty object inside of that empty object we need to specify the properties that the object is going to start with so in here we need to mention everything that it's going to have first of all the creator property which we just specified is at the beginning going to be an empty string title also an empty string at the start message also going to be an empty string tags is going to be also an empty string and finally selected file is also going to be an empty string we're going to convert an image to a base64 string just in a second okay we can put this in one line so it's easier to read and that's it we can remove the last comma great now we have that post data and we are using that right here in the value so how are we going to change the value of that state field using this on change well that's a bit harder considering in here we have an object that's in the state and we want to update just one of the object's properties to do that we can use this syntax in here as always we have a callback function that has that event as a parameter then we have the set post data which is a setter method for that state and then in here it would be easy if we could just specify an object and then in this case say creator and then creator is equal to e dot target that value right that would be okay that won't be all that complicated but it's not that easy because later on if we add a second text field that means that we would always override everything and simply have the creator we wouldn't have any other fields because you can see we are not specifying them in this object right here to fix that what we actually have to do is first spread the pose data so that's dot dot post theta and then we have the creator right there that means that in every text field if we do the same thing but only change the last property that means that all the data is going to persist while changing only the specific property of that specific text field that's it a bit harder but a great lesson to learn whenever i come across a piece of syntax that is a bit lengthier such as this one i copy it and then go to the website called mem.dev in here i can log in and it's going to allow me to train on that same syntax in here i can just click create a card and paste that snippet right there in this case i just want to learn this thing that's the hardest thing that's the thing that we have to spread and then use the creator we can set the text highlighting to javascript and i can say i just learned how to set the state using an object now it allows me to train it's going to keep asking me to do the same thing until i'm 100 sure that i can replicate this always and it's completely engrained in my memory i know that i need to spread it post data and then finally i have to do creator is equal to e dot target data value and that's it i click submit you can see it's correct and now since i know it i can click easy but if you don't know it you can practice on this and it's going to keep repeating so you can practice it every few days until you actually remember it great that's it just wanted to let you know that now we can go ahead and add multiple text fields this one is only for the creator i'm gonna put all of this in one line since we already know what is in there and now i'm gonna just copy and paste it a few more times we're gonna need it once for the creator once for the title then the message and then finally the tags great of course we have to change the labels as well so this is creator this is going to be the title in here we have the message and finally the tags and now we have to change the values as well this thing here is going to be a title therefore title is also going to be here in here and in here we have the message and finally in here and in here we have the tags that's it we now have four text fields now let's do the most important thing we're going to create a div that div is going to have a class name of classes that file input and then inside of there we have to use that package we install at the start it's called file base so at the top of our file we're gonna import file base from react minus file minus base 64. and now we can use it as a component file base and we have to specify a lot of properties in there so first of all the type is going to be equal to the file multiple is going to be set to false we only need one and then on done function is going to be set to a callback function where in here we do one destructuring we get that base64 thing and then in here we need to return or rather setpostdata and then we have an object in there we spread the post data and finally set the selected file to be equal to this base 64 we are receiving from here that's it we can also put this in one line right now that's it we now have all the inputs we are missing only one thing and these are going to be the buttons so first button right there the button is going to have a class name of classes dot button submit it's also going to have a variant of contained color of primary size of large type of submit and then finally it's going to have a full width property and the button itself is going to say submit you can see we have so many props in here so many but usually if you don't have this you would have to have a hundred lines of css for that nice looking button with material ui we just passed props and that's it we need one more button to clear the form for that we're gonna copy this one simply remove the class name we don't need it here the variant should be contained in both cases not container contained color is going to be secondary here size is going to be small and then in here we're going to have an on click function rather than type submit so on click is going to be equal to clear that's going to be a callback function to clear it and in here we can also say clear great now as we did with the handle submit let's create that clear so that we don't have any errors there we go and save it now if we go back to the browser we should see a nice looking form and we have a nice looking form but it's not perfect these inputs should be stretching and have some margins so let's see what went wrong there in here what we needed to do is have multiple classes here so we need to make it a template string and the first class is going to be classes that root to actually provide that padding and margin and the second one is going to be classes.form that should fix the issue let's see if it works save it and then go back as you can see now we have those margins and the last thing would be yeah in here we have full width value but we need to separate these words of course so if you do this like this and go back that's it we finally have a nice looking form and now that we make a post request we are going to be able to add a new post into our database connected to our server now let's add the api request and the action for the post request first let's go to the api and then in here we're gonna do export const create post in here we're gonna have a callback function this one is going to take in one parameter and that parameter is going to be the entire post after we get the post we can say axios.post first we have to specify the url and then we have to specify the data we are sending of course in this case the data we are sending is going to be the whole new post now that we are exporting this we can go back to actions inside of the actions let's create it export const create post is going to be equal to the same thing an error function which then returns another error function with a dispatch right there that comes from redux tank and finally we're going to do a try catch block inside of there try catch inside of the try we need to get that data so that's going to be const we destruction the data from the response and that is equal to await api dot create post this is basically making an api request a post api request to our backend server and we are sending a post right there finally we're going to dispatch an action the type of the action is going to be create and then the payload is going to again be the data just like so great in here we have the post and the post we're receiving it if you remember through here so in here we're going to say post great and finally if this is not successful we are simply gonna console log the error just like so now if you remember correctly we have to dispatch that action to do that we can go into the form and then in here we can import that use dispatch from react redux import use dispatch from react minus redux just like this great we have to use it right there cons dispatch is equal to use dispatch and now this allows us to actually dispatch actions the question is where do we want to dispatch it well of course on the handle submit once the user submits we want to send over a post request with all the data that user typed in first of all we always have to say event.preventdefault not to get the refresh in the browser and then in there we're going to dispatch an action so dispatch this time it's going to be create post and now inside of there we're going to pass all the data from our state post data you can see create post is still red which means we have to import it from actions so in here we can say import create post from dot dot slash dot slash actions slash posts just like that i can see event is not there so we have to specify it here and now we are making that request once we click the submit button great once the action is dispatched then we go to reducers right there in the post reducer and then what do we want to do once we go to the create well we have to send over an array of course we have an array of posts first of all we have to spread all the posts and then we have to add a new post and that new post is stored in the action.payload that's it now if we save that if we are lucky enough if we don't have any bugs this should actually work let's go back to our form let's try creating our first memory inside of here i'm gonna put creator as js mastery the title is going to be new year's eve 2019 the message is gonna be had a lot of fun i guess and then let's add some tags let's say new year and also happy new year people do that with hashtags right great now we have to choose a file okay i prepared a nice looking fireworks there let's save it and now let's click submit and hope for the best as you can see something happened and we got an array back array that has one file in it that seems great of course we're not seeing anything yet because our posts and post is not displaying anything but if we go back to our cluster and then in here you can go back to atlas and then click collections if you go into collections you can see the data that is actually in the database in here we have post messages and would you look at that that definitely looks like the object or the memory we just created which means we right now at this point successfully created a full stack marin application first our react application more specifically the form right there sent a post request to our backend application then the backend application communicated that to our database and that's it we have this file saved that means that now we can set up the posts and the post create some jsx there and that post is going to be there every time we refresh the page and we can keep adding new ones we are now inside of the posts component we are now successfully fetching the posts and now we have to actually do something with them so let's first form a nice looking grid to do that we are going to import grid and also circular progress from add material ui core in here we're going to say if not posts that length then show circular progress and that circular progress is just a loading spinner and then we're going to put else and then inside of here we're going to create a grid of our posts so that's going to be grid and let's just do it like this for now let me explain this thing so if there is no post that length then return this otherwise return this this means that if post stat length is zero then zero is full c this is going to make it to trudy which means that we're going to show a circular progress if both that length is something other than zero for example 5 10 20 then this whole thing is going to be equal to false then we're going to show the posts themselves great first of all our grid is going to have a class name of classes dot container it's also going to be of a type container so we're going to just put that there we're going to say align items equal to stretch and also set the spacing to be equal to 3. great inside of there we're going to use curly braces to indicate we'll be using javascript logic and then we're going to loop over the posts posts that map in a map we get a post and then for each post we're going to immediately return something notice how it didn't put curly braces there but rather just normal parentheses inside of here we're going to return yet again a grid but this time off type item we need to close it like so and now that grid is also going to have a few more things first of all a key key is going to be equal to post dot underscore id it's going to stay as item and then we can say xs which means how large is it going to be on mobile devices on extra small devices it's going to take the full width 12 spaces on small and larger it's also going to take six spaces great and finally inside of there we have our post now as props in the post we'll be sending this post that's it as we are mapping with our real posts now not generic ones we can send that individual value of a post to each post component great now that that is done we can go to a singular post component and implement the logic there inside of here we are going to import a lot of things from material ui that's going to be card card actions card content card media button and a typography again from add material ui core great then we're also going to import some icons from material ui to do that we're going to say import that's going to be thumb up alternative so just alt icon from add material ui and then it's not going to be core it's going to be icons and then thumb up alt so make sure to copy this in the description you'll have access to the full code of this project so if you just mistyped something or something doesn't work just refer down the description and copy and paste it then we have import delete icon from add material ui it's again not going to be core it's going to be icons and then forward slash delete make sure it is uppercase d and the last one is going to be import more horus icon there's an i there and that's going to be imported from add material ui icons and then more horiz just like that with that out of the way we can now start generating our jsx to do that we're going to have a card in here that card is going to have a class name of classes dot card inside of there we're going to have card media which is going to be just an image it's going to be a self-closing tag and it's going to have a class name of classes.media image is going to be equal to post that selected file that's it and finally title is going to be equal to post dot title okay so we don't yet have the post but we can immediately get it from props considering we are pasting it right there what we did here is we destructured the props like so great just down below we have a div that div is going to have a class name of classes.overlay and inside of there we're going to have two typographies so typography1 and then this one is going to have a variant of h6 and also it's going to say pose that creator so we're getting all data from the card the second one i'm going to copy this one is going to be of body 2 and this one is going to be about when the post was created we can use that moment library installed at the beginning that's going to be import moment from moment and now we can do it like this moment we pass in that post that created add and then moment has something known as dot from now and you call it as a function this basically says five minutes ago five seconds ago and so on that's it below that we're going to have a div and this div is going to have a class name of classes dot overlay 2. below that we're going to have a button or rather inside of that that button is going to have a style of color white like this and then we're going to give it a size equal to small and we are also going to add the on click listener on it with nothing in it yet just an empty function that button is going to include the icon so in there i'm going to say more horus icon and we're going to give it a font size of default just like that close it and that's our button now below that div we're going to have another div with a class name of details class name is equal to classes.details div is also going to contain a typography so i'm going to copy this one first the variant of this one is going to be body2 the color is going to be text secondary and then in there we're going to loop over our tags and add the hashtag before them we do it this way post that tags that map and then for each tag we want to do something and that something is return a string where each string is going to start with a hashtag sign and then immediately afterwards tag make sure to leave one space afterwards that's it below that we're going to have yet another typography this one is going to have a class name of classes.title it's not going the variant is going to be of h5 it's not going to have text secondary rather it's going to have gutter bottom great and inside of there we're going to remove this and say post dot message that should have been in the card content so i'm gonna add card content right there and put that typography inside of there great finally below the card content we have card actions with a class name of classes dot card actions inside of there we're gonna have two buttons they're gonna be really similar first one is going to be of size equal to small also of color equal to primary and it's going to have an on click function just like this we're going to leave it blank for now this one is going to have a thumb up icon so thumb up icon and the font size of that icon is going to be small just like so next to it we're going to say like and next to it we're going to add post dot like count in here later on we're going to have the like count now i'm gonna copy that whole button and in this one everything is going to be the same but this one is going to contain the delete icon and also it's going to say delete and we don't need the like account there okay looks like we have one error and that is that we are missing opening and closing curly brace there let's save it and if we did everything correctly our card should look pretty good right now and this error is saying that we don't have access to material ui icons that means that material ui icons is not part of the material ui core then to get access to it we're going to copy this part and simply install it so close the terminal run npm install and then paste add material ui forward slash icons once that installs we'll be able to run npm start and see how everything looks like let's run it that's it you can see we have a nice looking card with a lot of styles overlay we have also this created add function we can click this button which later that button is going to fill all of this input so we'll be able to change it and yeah everything looks good right now we don't have the functionality we cannot edit like or delete but this is the card this is the css now we can keep on adding new cards and they're gonna appear right there now is the time to implement all the other functionalities there's one thing we can do before adding all the other functionality and it's immediately going to make our application look so much better let's go back to code inside of here in the src folder create a new file called index.css we have to connect that index.css to our index.js file so let's do that here just say import dot slash index.css inside of that index.css we're going to add our svg background so let's go to chrome and you can visit this site svgbackgrounds.com in here we have a lot of backgrounds you can choose the one you like for me personally i chose this one so let's click that and then you can copy all of this css output let's take that and let's go back inside of the css file we're going to target our body and then simply paste everything we copied that should work let's save it and go back as you can see that's it already looks so much better now on to the functionality next logical thing to do would be to implement the update route so let's do just that i'm going to collapse our terminals right here and then go to server routes and then finally to posts we can add a new route just below and that's going to be router.patch patch is used for updating existing documents in here it's not only going to be forward slash it's going to be forward slash id and that's going to be dynamic for the reason that we need to know the id before we want to edit something so for the editing we need the id for the creation of course we don't because we're gonna just add a new id but for updating we need to know the id of the existing post and now let's call our new function update post of course we'll be importing that from the controllers and it would make sense to go ahead and create it so now we can go over to controllers and then in here let's start with the creation of that new function export const update post it's also going to be an asynchronous function and as parameters is going to have request and response first thing that we want to do is we want to extract that id from that params so how do we know we are going to receive this well if you remember we set our route to be this so that means that finally once we make a request the request is going to be made to posts and then one two three that one two three is immediately going to fill the value of id while using object destructuring we can also rename our properties and in this case we're going to have to rename our id to underscore id just like that moving further we're going to do one simple check to see if this underscore id is really a mongoose object id to do that we're going to add a simple if check and there we're going to check if mongoose.types that object id that is valid in there we pass in that underscore id so if it is not valid we can add that not at the start then we simply want to return rest that status of 404 and then we can say dot send no post with that id just like that on the other hand if the id is valid then we can update our post to do that we're going to call our model which is the post message and we're going to call a method called find by id and update on it there we need to pass the underscore id as the first parameter as the second parameter or the argument we have to pass the whole updated post but where are we receiving the data for the updates well we are receiving it from the request.body so in here we can say const post is equal to request that body that is going to be sent from the front end now in here we can pass that post and finally we have to specify new to be equal to true so that we can actually receive the updated version of that post we can get that through here const updated post is equal to and then this is an asynchronous action so what we have to do is add a weight in front of it now we have access to the updated post and also it is going to be updated in the database finally we can do rest.json and we can send over that updated post that's going to be it for the update route and the controller now let's try adding the client side for the same logic first let's go into the components in the form because that's where we will be dealing with the update logic in here we have to somehow get the current id of the post we're on what does that mean well if we go back to the page in here you can see these three dots at the top right corner that's going to be the edit button once we click that we need to pass over the id of this specific post to our form component that way we can change this from creating a memory to editing a memory under this specific id so let's do that this button is definitely under the post component moving on to posts and posts in here let's find that edit button and it looks like it's here we have the styles for it we have the size and there is the on click property but you can see we left it empty so in here now we have to actually do something we have to keep track of the current id to do that we are going to go back not only to posts but also to our app.js in here we're going to keep track of that current id why in the app because we have to share that state of current id between the posts and the form and our app is the only parent component that is parent to both posts and the form now later on we're going to refactor this to use redux but for now let me show you how to do it with just plain react in the app we're going to import the use state hook and then at the top we can say const current id and set current id then we can use the use state and set the id to be null at the start if you don't have the id selected now what we're going to do is we're going to pass that current id over to the form so we say current id is equal to current id just like that and we are also going to pass the setter methods for that id both in here to posts and also in here to form so set current id is going to be equal to set current id and again why are we doing this well i want to show you how data management would look like without redux you can see you have to bring something all the way up to the app.js and then send it over to all the components of course since we're sending it that implies that we have to go over to the form and now accept these as props so in here we can destructure and then use that current id as well as the set current id and just to say consistent we are also going to receive the set current id inside of posts as props now inside of posts we're going to pass that set current id prop one more time one level deeper to the post and this is called props drilling we are basically continuing sending the same prop over and over again to the most child component and that's the exact problem that redux solves great now that we have this we can know that also in the post we are going to receive that set current id right here along the post finally we are back where we were that now on the on click we can call that set current id and we can set it to be equal to post dot underscore id great now that is changing and it's not only going to be changed in here it's also going to be changed in the form and also it's going to be changed in the app so we wanted to bring that information over to the form so if we go there you can see now we are accepting that current id inside of the form what we're going to do now is in here we're going to add one if statement if we have a current id which means that if the current id is not null then we're not going to dispatch a create post we're going to dispatch something different and that something is going to be dispatch update post just like that but keep in mind with update post we need to know also the id so the post data is going to be the second parameter the first parameter is going to be the current id and else we are going to dispatch a create post so if we don't have a currently selected id that must mean that we are creating a post and not updating it that's great but you know that currently this update post is not defined so we have to go ahead and import it from here update post not only that we now have to go to slash actions slash post to implement it but actions are using the api so let's first go to the api inside of here we're going to implement the api call for our update post route that's going to look like this export const update post and in this case you know that we're receiving two parameters we're receiving in the id and also we are saving in the updated post or you can call it post data that's going to be equal to an arrow function with an instantaneous return and in there we're going to have axios.patch so to which url will be making that request well it's going to be url forward slash and then id so for the first time ever we not only have the url we also have the id specified because we need to know what post do we want to update and then as the second parameter we are sending over the updated post great now we can go to actions inside of the actions of course we're going to create another function which is going to be called update post in there we are receiving now two things not just one which is going to be the id and the post and then of course we have async dispatch and then in there we're going to have a try and catch block inside of the try we're going to be making that api request to update the post so that's going to be like this await api dot update post and we have to pass over the id and the post what is this api request returning well it's returning the updated memory or the post so we can get the response here but not only the response we can destructure the response and immediately get the data once we have the data for the updated post we can call this patch in there pass in an action of type update and also we're going to be sending over the payload which is simply going to be data if you've been working with redux for some time then you know that it's usually a good idea to have action types set as constants and then to import them in these files we're going to do that later in the video i just wanted to lay that out for you who were expecting that great now after we add the console log here so console.log error.message you know what is the next step after we do the action we have to go to the reducers so save this file and let's move over to the reducers posts.js in here we have to implement the case for the update post or let's see how did we call it we called it just update so in here let's add a new case that case is going to say update so what do we want to do on the update well in this case we want to return something of course and that something is going to be posts dot map a quick question do you know what is the output of any map for that matter so when we have array dot map what is the output of a map method it is an array so we'll be mapping over the posts array we'll be changing something in there and then we'll be returning the changed array inside of the map we have a single post and then what we'll do is we're going to have a ternary expression in there we're going to say if post that underscore id is equal to the action dot payload keep in mind that action.payload is the updated post so if the post id is equal to the action that payload that underscore id then we want to return the action.payload why because that action payload is the newly updated post or memory otherwise we want to return just the post as it was without any updates that's it great so what are the next steps the next step would be to update the fields of the form with the values of the post we want to update of course when you click this we don't want to start everything from scratch we want to have these values already in there and then we simply want to update them so that's our next step to do that we of course have to go to the form and then in here we have to fetch a new post you already know how to fetch some data from redux right we've been doing it so far inside of posts if i'm not mistaken inside of here we are fetching in the post so let's copy that use selector and let's also copy this line we can move that over to the form and inside of here let's first import that use selector from react redux i'm just going to place it inside of here and also now we're fetching all the posts but in this case we don't want all the posts we only want the data for the updated post to do that in here we're not going to return all the posts what we're going to do is we're going to have another ternary and that turner is going to say if we have a current id so if it's not null then we want to loop over state that posts and we want to call a find method on them more specifically we want to find a post let's call it p in this case that has the same id so p dot underscore id as our current id just like that so this is going to make sure that we find only that specific post if we don't have the current id though in that case we just want to have null and now we're not returning posts here it's simply going to be post because the find method is returning one singular thing great so now that we have the data for the post we'll just have to do one single thing which is going to be first import use effect and now use that use effect to populate the values of the form we can use the use effect like so we just call it it accepts two parameters first one is a callback function and the second one is called a dependency array in here we say when this callback function should be ran when what changes well when the post value changes from nothing to to the actual post then we want to run this function and then in here we're going to say if post exists then we're going to set post data and remember that is our state field here set post data and we are simply going to populate it with the data of the post that's it let's save it and see if it works okay we are back in here let me zoom this in and i'm gonna click this button there we go the values are populated and most of the work is done and let's change some things so first of all i'm gonna type javascript mastery instead of js mastery let's change this to new year's eve 2020. let's hope it's going to be good and now i'm going to add a new tag here which is going to be 2020. now i'm going to click submit looks like nothing happened right but let me refresh the page as soon as i refresh the changes are here that's good so the only thing we have to do is we have to initiate another get posts request after we update the post well let's first implement a few different things and one of these things is gonna fix that get posts immediately first of all once we're updating let's change this to editing a memory instead of creating that's gonna be as simple as going in here and then having the code in here and the only thing we'll be doing is using a ternary so if the current id exists then we want to return a string of editing so in here we're going to have editing and if current id doesn't exist then we're going to have a string of creating that's it as simple as that and we don't need this dollar sign great let's save it and see if that works and now we have creating a memory if i click this button we have editing a memory great the thing will the thing that we want to do next is once we click submit we want to clear all the inputs because that memory is edited and we want to keep moving forwards and we want to have this back to creating so to do that we have to implement this clear function we talked about inside of the clear first of all we're going to set the current id to be equal to null so we're going to reset it back to null and then also what we have to do is take all the default values right here we have them in the state and simply update the state again that's going to be set post data and we're going to set it to everything at an empty string great if i now save this that should work going back refreshing and now let's try to edit and let's just try sending javascript mastery one submit and that didn't do it clear function is implemented and if we start editing and i click clear that works but we also want to call clear function once we edit or once we create a new form so that's going to be clear right there or even better since we'll be using clear at both times no matter the if or the else we're gonna call it at the end right here i'll save it and go back and see if it works okay i'm gonna change this to javascript mastery 2 this time and let's click submit as you can see this returned to normal and in here if i refresh the post is going to be changed well remember how i told you that emptying these values are going to actually immediately reset our posts so that we don't have to refresh the page well for that we just have to do one more step and that step is going into the app.js and then changing this use effect from only having dispatch in here to having the current id why is that going to work well considering that we are now clearing the input and cleaning the input means changing the current id as soon as we change the current id in the app the app is going to actually dispatch to get post action and that is going to make sure that every change we are going to get new posts let's save it and see if it works i'm going to click the edit button and change this back to javascript mastery without any number click submit and it looks like it doesn't work well there could be a few reasons i just spent some time debugging this and i found out that inside of our controllers we are using mongoose here but we never actually imported it so go ahead and go inside of the controllers inside of the post and make sure to have this line that's gonna be import mongoose from mongoose great but not only that we had one small mistake in this file as well if you go right there you can see that we are updating the post where we are passing all the data we are receiving from the front end right there as the post well what is a post a post is an object that includes a title maybe a name a message tags and everything else represented but we forgot to send over the id as well because in the database each post has to have its own id so what we have to do is we have to create a new object just like so spread all of these properties from an object that we are receiving from the front end and then also pass in that underscore id now this is going to be our newly updated post and in here instead of the post we can have that post with all the things but only now we have the underscore id as well now let's try to save it and see if that works one more tip is that you don't have to refresh the browser once you make changes on the back end if only changes you made were on the backend you can just initiate a new request and don't have to reverse the front end so in here let's say we go a bit into the future and let's say new year's eve 2025. i'm gonna click submit and let's see this cleared out but i don't see that the year changed here i just noticed we're missing the title altogether here so let's fix that we can go to the post and then see where the title should have been and we have the creator here we have the time and then the title should have been somewhere around here there we go class is that title and then that's post that message but we never have pause that title right so to fix that we're going to add another typography just below the tags we can even copy this one and then bring it above the cart content inside of here this one is going to have a class name of classes.title and we can leave everything as it is but this time in here is going to be post.title and this one since it is a message it's not going to have a classes.title class great let's save this and see if it works as you can see we have the title now the last thing is to check if our update works let's change absolutely everything so it's going to be js mastery now let's go to year 2030 let's add a second exclamation mark and in here i'm gonna change the tag to 2030 again click submit and i spent about 20 minutes debugging it and turns out it was just a small typo let's go step by step first of all i noticed that we are using mongoose here but we forgot to import it at the top so let's do that import mongoose from mongoose and i want to guide you to the process of how i was trying to discover the error i just want to skip through the video or cut it out i want to show you that errors are normal and that we need to be able to fix them and let me show you that last error that we had or at least i had but it happens so if you do this and then if you change the title or the creator you can click submit and open the console after you open the console you get a message from js line 30 saying cannot read property underscore id of undefined if you click that you're going to notice that that's coming from actions so now if you go to actions you can see that line 30 is right here air that message and that's coming after we make this api request which could make you assume that the error is actually coming from the back end but it is not and here's a great tip for you never console log air.message because then you're losing the information just console log the error and that's going to give you more info so now let's do one more request to see what the error is going to give us if we go here try to edit the post and then finally change this to javascript mastery 2 click submit and you should be able to see cannot read property id of undefined but now we get where add posts js4 if you click that it actually turns out to be the reducer so let's go to the reducers inside of the reducers that's going to be line four and take a look cannot read property id or underscore id from action.paylad what whole time the mistake was that there is a typo so now i'm going to change this to payload just as it's supposed to be and i want to tell you that this happens it's completely normal so once you're going through the process typos are going to happen errors are going to happen but you need to be able to solve them step by step by using cons of logs or any other method as a matter of fact now let's hope that one more request for our update is going to be our final test if we now go ahead here let's try to change everything js mastery let's do new year's eve 2030 two exclamation marks and let's change the tag to 2030. i'm gonna click submit and let's see there we go all of the data was changed and that's it the message here is we need to be able to solve the errors and especially typos because they do happen next thing that we're going to implement is going to be the delete so right now if you click delete nothing happens let's see why is that well if you go into a post right there and if you collapse this terminal so we can see better you can see delete currently has no on click nothing is happening that means that we first have to implement the backend logic and then we're going to connect that to the front end so if we collapse all of this in the server first of all as always we're going to create a new route the route is going to look like this router dot delete great and now we also need to have access to id same as with the update because we need to know which post are we deleting and then we're going to call a function called delete post just like that now we're going to import it from the controllers delete post and then we can go to controllers to actually create that function inside of here export const delete post it's going to be equal to an async function that has request and response as parameters and then in there we also need to get this id so let's do that const we get the id from request that params that's good we're going to copy this line because we need to make sure that the id is valid so i'm going to paste that there and finally we have to implement the logic to delete a to do and that's going to look like this await post message dot find by id and remove and then in there we can pass in that id we are receiving from the params finally we can return rest.json where the message is going to be equal to post deleted successfully now that we have that route we can go to the front end and actually initiate it first of all we're going to go to the api and then in there we're going to implement that api call that's going to be export const delete post in there we receive only id this time we don't have the updated post because we just delete it and then we're going to call axios.delete we pass in the url and forward slash we also pass in the id same thing we did in here with the axios patch great now we know that we can go into actions and there we can create our action creator inside of here that's going to be export const delete post we take in the id and then we have the async dispatch and inside of there we have a try and catch block since we don't need to pass in any data inside of here we're gonna await that api call that's gonna be api dot delete post and we pass in the id since we don't need the response of this we can simply say this patch and then pass in the type that's going to say delete the payload can be the id we want to delete we don't need to do something like this const response is equal to this because we are not interested in the return data we only want to delete it and that's it and inside of here we're going to console log the error now one more time where do we go after we create an action well we go to reducers so in here we're passing over the id and that's going to be under the type of delete so inside of our posts we have to implement that delete right here and now what are we going to do when we delete something well it's going to be really similar to the update but just a bit simpler we're going to return posts dot filter and in here we have a post and we're going to basically return all the posts but we're going to filter out the one that we deleted and that's going to look like this if the post that underscore id is not equal to the action.payload in that case we're going to remove it so we're going to keep all the posts except the one where the id is equal to the action.payload now that our reducer is done we can go inside of the post and finally dispatch that action where do we do that and how do we do that well first of all we have to import that action and since we don't have the reducer setup in here yet we have to do that as well we can do that by importing use dispatch as we always do from react redux then in here we're going to initialize the dispatch to be equal to that hook use dispatch and we also have to import actions so inside of here we're going to import delete post which we just created from that dot slash dot dot slash dot slash actions slash posts and finally moving down we can dispatch delete post in here we need to pass over the post dot underscore id that's it now we did the whole circle of first doing the back end connecting it to component creating actions api calls and reducers for the delete request great let's see if it works before we actually delete something let's add a new card let's say that john went skydiving so we're going to put skydiving there and he's gonna say it was awesome great and in here we can do some tags so let's do skydiving i downloaded the image of man skydiving and we're gonna submit it and let's do that great as you can see john is skydiving and it is awesome now let's try to delete the initial post as you can see nothing happened so let's start debugging it first of all we're going to go into the controllers part of our server and then in there i want to see if the delete request was indeed made so inside of here i'm going to console.log delete just so we know that we reach this point in our code great so if i now do that and then try sending another request from the front end let's see what happens we do get an error here and the error says unhandled promise rejection warning reference error underscore id is not defined at delete post line 41 that means that in here we don't have the underscore id and yeah that was just a small typo in here i copy this line but it should have been just the id so we're going to leave the id there save the page and then go back to the browser if we go here and now press delete let's see what happens the post was successfully deleted that's it amazing now let's add the ability to like the post to implement the liking functionality we have to do one full circle and that's something i want to point out is that once you have the proper structure set up using redux controllers route that's extremely scalable it's easy to keep adding new things onto it just by following structure so now what we're going to do is as we always do follow the structure first we are going to add a router that patch request and it's going to be to forward slash id and forward slash like post just so we know that this is the route for liking why is it a patch request if we said that patch request is used for updating well if you think about it liking something actually is updating it it's updating the number of likes that the post has so moving forwards we add the function that's going to be like post and we have to import it from controllers like post here then we move over to controllers and then in here we can create that function export const like post is equal to an async function where we have the request and the response and in here we also have to get the id so we can do the same thing we're already used to great once we get that we also have to check whether this is valid so we're going to use this now in this case we first have to find the post we're looking for and that's going to look like this const post is equal to a weight post message dot find by id and then in there we specify the id this is going to return us a post and now we have the updated post whereas const updated post is going to be equal to a weight post message dot find by id and update where we pass in the id and now this is the crucial part as the second parameter we want to pass in our updates so that's going to be an object in there we want to increment the like count so we're going to set like count to be equal to post dot like count this post is the post we're fetching right here and then what we simply do is increment by one and then with update requests we have to specify the third parameter where we say that new is equal to true this is inside of an object where new colon is true great that's it and now we have access to the updated post below that allows us to do rest.json and then in there updated post you can notice that this thing is really really similar to the update post great now we're gonna save that and let's move on to the frontend part as always we first have to add the api call and that's going to be export const like post we need the id and then we have an error function where we say axios.patch this time the url is going to be url forward slash id which needs to be a dynamic value forward slash like post just like that as always once we have the api request we can move over to actions and in here let's create the like action export const like post we have the id in there and then finally async dispatch where we have a try and catch block inside of here we want to get the data of the newly updated post and that's basically going to be the same as the update so i'm going to take this whole part paste it in here and the only thing we want to change is from update post to like post that's it in here of course we're gonna console log the error oh and as well you can see we have the error here since we're just liking we don't have to have the post here we just like it and that's it we don't have to provide what we want to do with it that's it finally we go to reducers posts and in here we have to implement the logic for liking posts and the logic is actually the same as for the updates that's why i said that these are really similar so first we map over the posts we check what is the one pose that changed or what is the one pose that was liked return the post with a change or if the post is not liked then just return the post as it was since they're completely the same we could do something like this where we copy the same thing and then we say like but what we can also do is just put two cases one below each other and then they both are going to do the same thing finally we can go to posts and then the post component and in here with the delete post we also want to import like post moving below to our button we just need to add an on click which is going to say dispatch like post and then in there we send over the post dot underscore id that's it let's see if it works i'll try to like this post as you can see we have one like with our current implementation one user can like a post as many times as he wants if we want to give users the ability to like the post only once per account we have to implement accounts what does that mean that means that we need the full authentication system we need registration we need login we need to allow users to reset their passwords create accounts and do everything else that's usually called authentication you guys can try to implement that by yourselves but if you feel like you cannot just let me know feel free to like this video leave a lot of comments and if this video goes well i might even do the third part where we're going to add authentication to this mern project to make it even more complete currently we're fine with the ability for users to like the post as many times as they want so that is completely fine with that said let's move forward with our app what else do we need to do to make our app better and our code more professional and presentable well first of all i noticed that we have a slight mistake here the title and the description have the same font or the same styles so let's go ahead and change that you can go to the post.js and then inside of the post.js that's going to be somewhere around here typography this is the body2 that's not what we're looking for there we go pose that created that we are looking for the title there we go post.title that is it and then in here we have post dot message what we want to do for the message is we want to make it a variant of body 2 and we want to give it a color of text secondary just like this and we can also say component is going to be equal to p it's a p tag and we don't need this gutter bottom if we go back and refresh the page we get it was awesome let's add some more tags and some more words to the description so we can see it better in here i'm going to initiate our edit which now fully works i'm going to remove this exclamation mark and i'm going to say it was awesome this was the first time i sky dived ever great experience just like that and we can say skydiving 2020 uh great time just like that and click submit as you can see now this looks so much better our card now has the title description is properly styled and we have some hashtags right there and i noticed one more thing to make our app just a bit better currently our tags are not working as they're supposed to as you can see they're all kinda the same hashtag right even if you try to change them and then add spaces it's still not going to be many different hashtags so later on if we want to implement like search posts by hashtags this is not gonna work what we need to do to make it work is go back to our form and change the way we save our tags that's going to be in the form folder and then in the form component and that's going to be around here as you can see this text field is used to save tags currently we're just saving them as a string what we want to do though is do e target.value this is a string of tags we want to call the dot split method on it and we want to split it into an array by a comma so in here we are saying split this string by commas no space afterward and then give me an array of all the tags if we now save this and go back we should be able to edit this into a fully functional post with hashtags let's take a look we are back in here i'm going to click edit and now i'm going to try putting all of these just as tags with comma separated values and click submit there we go this looks so much better now we have three different hashtags skydiving 2020 and great time it's great in regards to the cards i think our work is done we can add a few more cards just to get a feel of how this looks like as you can see i added one new card it is new year's eve 2019 james said that it was the best new year's eve ever and that he was in times square amazing so our cards look pretty good we can like them we can delete them i just noticed like we need to add a space in here between the like the icon and the number so let's do that right now for that we're going to go into post right here and then find where is our like button you see we could add a space here and here but that's not going to do anything that's not going to be interpreted by our jsx what we need to do is add a code for the space character it is and and b sp semicolon this is the same as you wrote a space character but we need to use that in here so let's add that just before the like and also after the like i think this is gonna be good let's test it out save it and go back to the browser as you can see this is much better we have some more padding in here and we can like the post we're moving on to an incredibly important thing and that is is our website or the application mobile friendly is it responsive for that you can right click and click inspect this is going to open the responsive view to view it in a mobile device click here into responsive and choose a phone let's choose iphone x and would you look at that this application is responsive out of the box because we were using material ui did you think we're going to have to do a lot of work to actually make this accessible for mobile devices well that is not the case as you can see the application is fully responsive both the form and the cards the only thing we could do is put the form on the top of the screen for mobile devices because as you can see currently it's kind of buried down there how would we do that well let's take a look the form is currently in here and that is inside of this container material ui container so what we would need to do is change this container into display flex like this give it a flex direction of column but i think it already has that and then i think we can do flex direction yeah flex direction column reverse that's what we want to go for as you can see that didn't do it i'm guessing because there is another container inside of there so maybe we need to be changing this one this one is for the cards as you can see but this is the one we want to be targeting not the one above rather just this one so in here i'm gonna do flex direction and that's going to be column reverse and would you look at that our form just to the top so now if we have 10 20 or 30 cards you wouldn't have to scroll you just have to put the form at the top so this was the material ui spacing 3 grid so if we go back to the code i'm just gonna search for spacing is equal to three because that that's what our container has and that is currently in here in the app our app is wrapping our posts and the form so the only thing we have to do in here is something like flex direction and then let's try to do column reverse we'll see if that works i'm not sure if they have built in property for flex direction if we save it and go back let's see if that worked unfortunately it didn't at this point i would just go into the material ui documentation and take a look but let's give it just one more shot let's try with just direction instead of flex direction because in here you can see it's just justify just the line items so maybe who knows that works and looks like it did would you look at that material ui is really intuitive but we don't want this to happen for desktop devices so we only want to apply this if we are on mobile because of that i'm going to copy this and simply give it a class name so we're going to say class name and this is going to be something like classes that a main container just like that now we can go into our styles of the app.js let's take a look that is right here in styles.js and then in here we can say main container do it like this as an object and then in there we want to do flex direction and that is going to be equal to column reverse but how do we do that only on mobile material ui offers something known as breakpoints they are simply media queries so the only thing we have to do to make this work is put the array sign and then in there we're going gonna say theme dot breakpoints dot down and then you call it as a method and then in there you say sm as you can see we have sm excess medium large and extra large so in here we're basically saying run the css after this only for the devices that are small or even smaller than small like extra small and then in here we can move all of our styles that we have here and that is it as you can see our team is not being declared so we have to import our team right here make styles theme again if you're not familiar with what is happening right now it is just from the docs you can go ahead and research material ui into a bit more details or i can create a fully separate video on material ui if you'd like me to do that feel free to leave a comment down below so in regards to the mobile friendliness we are fully done works on mobile and works on desktop that is great if you want to you can make it work on tablets as well there shouldn't be a lot of problems but this is good for now our next step is not going to add new functionalities to the app or make it look better it's going to make our code look better and be more professional if you're employing for jobs and if you put the code on github you want to make it as good as it can be no errors no silly indentations all around the place like this or spaces running around you want your code to be as professional as it can be because later on you're gonna work in themes so what people often do in redux is they add constants for their action types currently if we close all of this so close all the files and collapse the file tree by clicking this icon right there we want to go to client and then actions right here take a look we have all of these strings right here this is a string this is a string all of our action types are indeed strings right so what do you think would happen if for example i misspelled this from fetch all to fetch all like this there is a typo but maybe while you're coding you don't see it of course this would break our application but here's the catch take a look there is no error and even if you go to the browser you would see okay it's not loading something is not working and even if you went to the inspect element you wouldn't be able to find any errors because there are none you simply misspelled a variable but it's not like this it's not like when you have a variable cons test is equal to test like this and then you want to do a console log test and then you mispell it here like this it's not the same situation because in here it's immediately going to say this variable doesn't exist there is an error but it's tricky working with strings right so this is why people have figured they're going to create constants for these action types so how can we do that well we're going to create a new folder in our src folder called constants inside of our constants we're going to create a new file called action types dot js and then inside of there we're going to create a lot of separate variables for these strings fetch all create we need more for update delete and everything else that we have so if we go to action types so in here we're going to start creating all these variables const create is going to be equal to create const update is going to be equal to a string of update or uppercase then we have cons delete is equal to delete like this we have const fetch all is equal to fetch all and then we finally have const like is equal to of course you guessed it an uppercase string of like of course we don't want to have this here because as you can see we are never using it so what we want to do is we want to export all of these so we can do it like this export const create update delete fetch all and now we will be able to go to posts and then import all of these types or action types right there right before the first line i'm going to say import open curly braces fetch all create update delete and like we're importing all of these from dot slash constants slash action types just like that and now what we're going to do is in here instead of this string of fetch all we're simply going to use this variable the same things go for create update like and delete make sure not to misspell something but let's add all of the variable names right there oh looks like we used the update for like as well so looks like we don't need the like after all i'm going to get rid of that go to action types and remove the like so now here's the thing if you misspell something like this it's immediately going to give you an error this might seem like a lot of work to actually implement this import it and then use it here but really trust me if you misspell a string here you can spend hours and hours looking for an error and you won't be able to find it easily but with this you're just making your code less error prone and more scalable as you keep adding more controllers more actions more reducers you'll just keep adding different variable names and not only that we can use these same action types we used here in our reducers because they are the same so in here i'm also going to import the same thing and then we can change all of these to our normal variables i'm just going to remove this and let's do it like this fetch all looks like in here we do have the like case but we are using only the update so we don't really care about that great now we implemented constant action types and we just made our code much more scalable and much less error prone if we go back to our application it should still work just as fine great that is done let's move back to our code and let me show you one of the final things i want to show you on this project again we're going to close everything collapse it and this time we're going to go into our server more specifically the index.js file of the server we have this connection string right here we also have the port right here and if you think about it in this string you can see our username you can see the password of our user and you can also see the name of the database that info should not be publicly available you shouldn't be posting your projects on github like this this needs to be stored somewhere where other people cannot have access to your passwords or secret api keys so how can we fix that the only thing we have to do is create one new file in our server.js and that is going to be called dot env env stands for environmental variables and these are files that are only going to be accessible in here on your pc these are not going to be posted on github so now in this file you can add all of your variables for example let's start with the port first the only thing you have to do is take this port and that is going to be the name of your variable then followed by an equal sign you can specify the value for the port now this value should be 5000 but let's change all the other values we're also going to take our connection url so connection url is going to be equal to this string i'm going to copy the string and paste it right here and that is going to be equal to connection url of course with an equal sign and without the string signs just like this for these variables to be visible by our application we need to install something called dot env so you can press mpm i dot env like this once we save that our application will be able to read the process env variables that is installed and let's run our application even if you didn't install it or if you had it before you still need to press ctrl c to close the server and then start it again for the variables to actually take place finally we have to import dot env from dot env and then we have to call just at the top dot env dot config just like that let's save it and see how it goes this is saved our server is running on port 5000 and if we go back to our application you can see everything works perfectly how can we know we are changing something well let's try to console log this port or even we can just change it and then you'll be able to see it in the console right away i'm going to say 10 000. if we do that save it and rerun the file it's still saying server running let's see yeah it immediately changed so we're running on port ten thousand we don't wanna do that because that would break our application our front-end is expecting localhost 5000 so let's go back and change it to 5000. now we are securely storing our connection url inside of our.env and since r.e and v is not going to be saved on our github what i like to do is i like to do dot env.example this file is going to be published to github so in here we can give an example of what all people need to have in their environments for this to work so in here we're going to say url string and then in here at the top we can just say port that way they know that they have to add their own thing in here for this to work great now our application works and it works really really well people can create memories edit memories like them delete them it is a fully functional crowd application we can start on the front-end side we can first start adding on the navigation bar the items for the login and registration so once we click that we'll be redirected to a different form the form for login or register so let's do that first if we go back to our code you can head to client we can go to src components and then right inside of here we can create that nav bar if i remember correctly we also had a bit of a navbar before but we didn't have it as a separate component so if we go to app.js you can see that our nav bar is here so we're going to divide that into a new component so inside of components we can create a new component it's going to be called navbar and now we can create a file called navbar dot js and also styles dot js we're going to copy what we have so far in our app so right here and i'm going to create a rafc a react function component with exports and we're simply going to paste what we have so far okay that's great as you can see i'm using eslint so some of the things are going to get changed immediately but don't worry about that and finally we have to import some classes so in here we also need our app bar and typography so i'm going to go here and say import what do we need the app bar and typography from add material ui forward slash core and then finally we also need our classes so to do that i'm going to switch this back to the normal return function right there and what we need to say is const classes is equal to use styles of course right now we don't have the styles but we have to import them so again as we always do i'm going to give you all the styles right away right here you can simply copy and paste them they're going to be down in the description for absolutely all of the components now at the top of the file we can say import use styles from and that's going to be just dot slash styles a lot of you guys mentioned that you like these applications and that you like building everything out and even though you prefer that i simply copy and paste the styles for simplicity and time saving purposes you'd want to learn a bit more about material ui and how to styles things with it so what do you say do you guys want me to make a separate material ui video where i'm going to teach you how to do everything material ui and also how to do the styles let me know in the comments down below okay with that said looks like we are missing one thing from our navbar and that is the link to the memories image so if you go back to the app you can see that we simply need to import it i'm going to copy it from here also i'm going to remove these things right there because we don't need them anymore and now in here we have to import that path now the pad is going to be just a bit different it is going to be dot slash and then dot slash images memories png okay with this we haven't done anything special uh we just removed our navbar so to bring it back we have to go to the app.js and then in here we need to import that nav bar if you simply start typing in visual studio code it's going to immediately import that for you so that's really handy i'm going to put it right there and that is going to be a self-closing component if it didn't import it for you just make sure to say import navbar dot slash components and then nav bar nav bar okay with that said if we go back you can see that we have everything we had so far so why did we even put it in a new component in the first place well now we're going to make it more complicated so we didn't want to clutter the app we want to have everything in its special components okay so what else do we need in this navbar well we're going to change it a bit so inside of here i'm going to create a new div that div is going to have a class name of classes dot brand container and we're going to put all of these things inside of it so now we have a div and we have a typography and image right there this typography is going to be of a component which is equal to link because it's going to be pointing to our home so we can say to and we can just say slash because it's going to be our main route and of course we have to import link from react router dom also i'm not sure if installed react router dom looks like i missed that so what we have to do is open our terminal one more time we have to close this from running by pressing ctrl c and then y and you can simply say npm install react router dom yep we also need that because now we're gonna have a complete app where we're gonna route things so you can wait until that installs and we will simply restart the application by running npm start great now we have the react router installed as well and that's not going to be a problem okay that's going to be it for our typography and that's also going to be it for our image so moving below just below our div we can create a new component which is going to be called toolbar that toolbar is going to have a class name of classes dot toolbar and down below we're going to show some logic depending on if we have the user logged in or if you don't so right now i'm going to create just a mock user so we can say const user is equal to null later this can be filled with an object with a real user or maybe the user is not logged in so what we can do is we can do something like this if user exists right if user exists then we're going to show something right here and then we can use another ternary to say else show something else right here so we'll be showing something if a user is logged in and something different if a user is not logged in if the user is logged in we want to show his information so in here i'm going to create a div with a class name of classes.profile in here we're gonna have an avatar author is simply going to be a small circular image displaying how a user looks like or it's simply going to show a letter of their first name so we can say avatar class name is equal to classes.avatar or it's going to be classes.purple yep and then we have an alt tag alt is going to be equal to user.result.name and then it's also going to have an src so src can be equal to user dot result dot image url so later on when we actually get this user we want to display all of these informations finally if it doesn't have an image we want to show the first letter of his name and that is going to be user but we need to open a block of logic here user dot result dot name dot car add and simply call it and say zero so we want to get the first character that is it for the avatar now below we want to have a typography so we're going to say typography the class name is going to be equal to classes dot user name and variant is going to be equal to h6 inside of there we can simply open a new block of code and say user dot result dot name the last thing that we need to have is the button to log out so i'm going to create a new button the variant is going to be contained like this and a class name is going to be equal to classes dot log out we are also going to have a color and that color is going to be secondary we need to have an on click property but we're going to leave that empty for now and finally we have to write what the button is going to say and that is going to be simply logout great so this is the block of code we see if we are logged in if we are not we simply want to show the button to log in so let's create that button that is going to be button it's going to be a component which is equal to link and it's going to have a to property to forward slash auth so this one is actually going to redirect us to a different page where we're gonna show the authentication it is going to have a variant of contained and a caller of primary what the button is going to say is simply going to be sign in so in here we can say sign in okay and now you can see we don't have a few components imported so that's going to be a toolbar and a button so right here we can import the toolbar and the button great so now if we save that let's see how does that look like okay we first got an error because we are using a link outside a router that means that we have to actually use our react router dom to make our app multi-page we make our react apps multi-page using react router dom so we can do that if you go back to the application and now inside of here we can import some of the things from react router dom these things are going to be browser router switch and also route from react router dom great now inside of here i would first like to move this thing into a new component because we'll be adding a lot of things to it we want to keep our app clean so i'm going to copy all of this with the grow and we want to create a new component so i'm going to create a new folder called home create a new file called home.js now that we have the home js component in there we can also create an rafc and simply paste everything that includes this grow right here of course we'll have to import some components so i'm going to copy the imports from the app.js and paste it right here container grow and then grid you can also see that we are missing the posts and the form so let's import that import posts from dot slash it's going to be dot slash posts forward slash posts like this and then we also need a form so that's going to be import form from dot dot slash form forward slash form okay now we have the form as well and you can see that we're missing the current id and the set current id so how do we get that well if you think about it we can declare it right here and not have it in the app because because the app shouldn't be doing any major logic especially not with the posts ports are only contained in the home so we can actually use this dire logic and move it all the way to our home first let's delete this thing that we copied so inside of here we no longer have this what we have now is going to be self-closing component which is simply going to say home okay with that said we can copy this entire part and we can paste it in the home component my eslint again turned this into an instant return but i'm going to bring it back and create a normal return just so i can put these things here so let me just space that out and as you can see now we have the current id and the set current id right there we have to import the use state use effect get posts and the use dispatch though so we can head to the app and we can mostly get all of the imports from here you can see import used this patch from react redux so let's copy that then we need get posts we also need to import that so that's going to be around here but the pad is going to be different it's going to be dot slash and then one more time dot slash okay and the final thing is to import use state and use effect from react with that our component is filled and now in the app we can get rid of this extra logic there we go take a look at how many things we don't need right now to clutter our app we have everything in the home so let me let me remove these things we don't need that no need for any components right now and the only thing that we have is the nav bar and the home and as you can see we have that and i think i removed the import from react router dom which we are going to need yep that is right here so i'm gonna bring this back and now we can implement our react router so how can you do that well you have to wrap everything in the browser router so i'm gonna do that right now browser router and then we have our container right there then we're going to have a switch statement right here so you can say switch and i see that i didn't name it properly so i'm going to rename it the switch right there and then inside of the switch you need to have a few routes so i'm going to create our first route that route is going to be self-closing tag and we're going to simply say path is equal to slash so this is our home route it needs to be exact and the component is going to be equal to home component we have to import it right there then below that we're going to add one new route this one is going to have a path of auth and the component is going to be called auth this component is not defined yet so we have to create it let's do that right now inside of our components i'm going to create a new component or rather a new folder called auth inside of that odd i'm going to create a new file called auth.js and also we're going to create styles.js for the odd file again i'm simply going to say rafc and by the way if you don't have that that is going to be a package uh let me take a look it's going to be es7 react redux draftql snippets so you can download that that's going to autofill the rafc for you okay and then in here for now i'm simply going to say auth that is going to be it okay and i'm using eslint and i don't want this to be changed on instant return because later on we will need something i'm just going to say const state is equal to null here okay that way everything is going to be centered like this okay with that we now have to import this component and again if you simply type it and click right there it's going to be imported right for you okay so with that our routing should be done as you can see we have our nav bar it's not inside of the switch so that means it's going to be showing up always and then we have our switch which means switch between these two components either show the home or show the auth and of course we have to remove this home from the bottom because we are showing it right here okay now can we actually see this in the browser let's test it out and there we go everything is as it used to be but we made a few different components we created the one for the navbar and we created a home component with the form and all the posts now let's try clicking the sign in and see what happens and there we go we are routed to a completely different component that now says auth this is the place where we're going to implement the login and registration form that seems like a valid next step so let's do that next okay let's start creating the layout for our auth form inside of the auth.js we're going to first import a few things and these are going to be again avatar button paper grid then we're going to need a typography and finally a container all of these are going to be imported from add material ui forward slash core while we're here we can also import the styles meaning use styles from dot slash styles and of course we have to create those so again linked in the description are going to be the styles for this specific file i don't want you to spend time on writing css i want you to focus on the important things which is in this case authentication okay with that said we can say const classes is equal to use styles and call it as a function now we can start creating the layout for our odd form and it's going to look like this first of all we're going to wrap everything inside of a container that container is going to have a component property which is going to be equal to a string of main it's also going to have a max width property which is going to be equal to xs down below we're going to wrap everything with a paper so we can say paper and that paper is going to have a class name of classes dot paper and also an elevation of three this is simply going to make a white style div that looks like a paper and there we can have all the inputs inside of that now first thing inside of that is we're gonna have an avatar and that avatar is going to have a class name of classes.avatar finally inside of there we're going to have a lock icon so right inside of here you can create something like this lock outlined icon and that is going to be a self-closing tag that we have to import so at the top let's import that icon it's simply going to say import lock outlined icon from and in this case it's not going to be add material ui core it's going to be add material ui forward slash icons and then forward slash lock outlined there we go now that we have that we can continue with our form below the avatar we're going to have one typography this typography is going to be of a variant which is going to be h5 and it simply needs to say either sign up or sign in depending on what we want to do so right now i'm going to create once again a mock variable for now which is going to be called is sign up and we're going to leave that to false right now based on this variable we're going to change a lot of different things in the form so right now we can open a new logic block and we can say if is sign up then we want to show something like a string of sign up otherwise we want to show sign in now below that we're finally starting with our form our form is going to have a class name of classes dot form and it's also going to have an on submit right now we don't have announce a bit but we could as well create it so i'm going to say on submit the function we're going to call is going to be called handle submit so just right here you can create a const handle submit function there we go for now we're going to leave it blank now inside of our form we're going to have a grid that grid is going to be of a type container and it's going to have a spacing equal to 2. inside of here we can show all of our inputs so let's first start with the first name and the last name remember we only have the first name and the last name if we are signing up if we're already signed in we don't need that so we can open a new blog and we can say if is sign up then we could use the ternary but we can also use the end and operator so we can say is sign up only if it is sign up then show something and in this case we're going to show an empty react fragment and then inside of there we're going to show two different inputs so these are going to be text field elements we can say text field like that and we're going to have a few different things there we need to have a name so name is going to be equal to first name then we also need a label which is going to be equal to first name we need a handle change method so i'm going to say handle change here we can go ahead and create that handle change right now handle change is going to simply be equal to handle change so let's create an arrow function here const handle change is going to be equal to an arrow function okay what else do we need on our input we need also the auto focus because this is going to be the first element we want to focus on and then we can say xs is equal to 6 and we'll need a lot more things i'm going to explain why this is going to be different in just a second so this is going to be a self closing tag there we go now of course we're going to have one more for the last name we have to change all of these things then we're going to have multiple more text fields for passwords for confirming passwords for email and all of these are going to be kind of different but in most cases they are going to stay the same so we don't want to have the inputs that have like 10 different props what you want to do when you have most of the same components most of the components that look and behave the same is you want to create a new custom component which is going to generalize the logic that way you don't have to write everything for each one of them you can simply create a one that has all the things and then only specify the things that change it might be complicated but let me show you what i mean this is a really really good practice in react so inside of here instead of our auth i'm going to create a new file called input dot js that input is going to be an rafce a simple component and we're going to import a few things from material ui these things are going to be text field we're going to import a grid we're going to import an input adornment and we're also going to import the icon button from react material ui and that's going to be core okay great and i also forgot like in here we don't only need a text field we need to wrap each text field with a grid so it would look something like this and then each grid would have a property of xs is equal to 6 and then md is equal to 12 or something like that so you can see here we have this grid once but then again you need to have it for each new text field and you can see it it kind of adds a lot of code it makes it unclean a lot of repetitive code at least you can see so now we want to change that we want to make a generalized input field so to do that we can create one grid right there and all of our inputs are going to have that grid that's going to save us the trouble of writing this multiple times this grid is going to be of type item it is going to have the property of xs equal to 12 but what if we want some inputs to take only half the width then we can do something like sm is equal to 6 but now all of them are going to take half the width so we have to have a special prop we can name it something like half and then if half is true we want this to be 6 otherwise we want this to be 12. so see how we can make it dynamic okay now inside of there we want to have a text field text field belongs to material ui and it is going to be a self-closing tag i'm going to expand it on multiple rows so we can add our props inside of there each text field needs to have a name so i'm going to say name is equal to name right there because name needs to be dynamic as you can see right now we don't have a name so all of these things we have to import as props so inside of here i'm going to add a name then each text field needs to have an unchanged property so i'm going to say on change is equal to handle change then we have a variant that is equal to outlined this is the same for absolutely all text fields so we don't have to change that another thing that is the same for all text fields is going to be required we don't have to send that as a prop that is always going to say the same all of them are going to have the property of full width then for the label we have to change that so i'm going to say label is equal to label and we're going to pass that as a prop finally auto focus is going to be equal to autofocus and type is going to be equal to type and one final thing that's going to be happening only on one input is going to be called input props like this with a capital i capital props that is simply an icon that we're showing on the right side of the input if we want to click it and that's going to be for show password you know that field when you have a password then you you're not sure what you typed in you want to click that and then it's going to show it to you so we can open a new block and then we can say if name is equal to password like this then we want to show a block of code so you can open this and say end adornment is equal to and in here you can use the input adornment that's going to be a component the position is going to be set to end so position set to end and all that we need is going to be an icon button that icon button is going to have an on click property which is going to be equal to handle show password and in there we're going to show if type is equal to password so if type triple equal to password then we're going to show an icon that says visibility a self-closing tag otherwise we're gonna have an icon that says visibility off and it's also going to be a self-closing tag we can now this is going to be the end adornment but if we don't have that we can simply say null don't show anything and if you know react or javascript you know that when we have a ternary operator with the second value being null what you can do is simply change this to end end and then you don't have to provide that null right there great so if you save that you'll see that we're missing quite a few things that we need to import here and this is actually good because this means that we are taking all of the things that we need in here for this special input and we are importing them right here and not in our auth because in that way we're cluttering our odd component which by itself is already be complicated so let's import those icons right there import visibility from add material ui icons forward slash visibility i'm going to copy that line and the second line is simply going to say visibility off great now all of the other things that we need like handle change label autofocus we're importing from here so let's do that name handle change we need a label we need a half then we need the auto focus the type and finally the handle show password with that our custom input is done you can see we are exporting it as the input finally we can import it right here import input from dot slash input great now instead of typing all of this we can remove the grids completely we can remove that this as well and we're going to rename this to input instead of a text field and now as you can see we are passing only the props that we need name is equal to first name label is equal to first name we're passing the handle change method and everything else that we need in this case i think we simply specify the property half so we don't need to say the xs is equal to six we can simply say half and that is going to make it six and for the second one we don't need the auto focus as well because we have that and we can say half as you can see this makes our inputs a lot slimmer we don't need to have something like let me take a look something like variant outline for each one required for each one full width for each one and all of these things we simply specify what we need and now we can continue with all the inputs that we have both in the login and the register form so let's create them we have a new input this one is going to have the name of email a label of email address and a handle change which is going to be equal to handle change finally in this case we need to have a type and the type is going to be equal to email below that one we're going to create one new input also a self-closing tag this one is going to have a name is equal to password it's also going to have a label which is going to be equal to password and it's going to have you guessed it a handle change equal to a handle change the type is going to be of course password but what if you want to click that button which means show password in that case we have to change this from password to simply text that means that we need to have some kind of variable that's going to manage our show password and that is going to be a state so we can do that right now we can import react as well as the use state hook at the top and now we can create that show password field so right here i'm going to say const make a new state and we're going to say show password and set show password so this is going to be our state and that's going to be equal to use state and at the start it is going to be set to false okay so now based on this state we can say if right here i'm going to delete this if show password is true then show text otherwise show password okay and finally the final prop that we have to pass is handle show password is going to be equal to handle show password and what is that well that is going to be one function that is going to handle the show password obviously and the handle show password is going to be an arrow function handle show password that is simply going to toggle the state of the password so we can say like this set show password and then in here we need a prep state so previous state whenever you're changing the state using the old state you have to create a callback function and then you have to get the prev show password and then what we want to do in here is simply say if the previous show password is something we want to say false and then previous show password that means that we're toggling it so if it's on turn it off if it's off turn it on and we're passing that over as a prop handle show password okay there we go now our input for the password is done below that we want to have one for the confirmation and again the password confirm field is going to show only if you're on the signup form not on the sign in so i'm going to say if is sign up then end end then we show this input field this input is going to have a name of confirm password it's going to have a label of something like repeat password and it's going to have a handle change again be equal to handle change finally the type of this one is going to be password okay we have all of the input fields that we need right now finally we need a submit button so right below the grid i'm going to create a button and that button is going to be of a type is equal to submit so we're going to submit the form on this button it's going to have a full width property also a variant of contained and a color of primary as well as the class name of classes dot submit and now inside of that button we want to say either sign in or sign up so we can again use that property is sign up if it is sign up we're gonna show sign up otherwise we're gonna show sign in great so now it would make sense to take a look what do we have let's go back to the browser and see if we have the odd right here and there we go take a look at that we have our sign in form but right now there is no way for us to switch between the sign in and the sign up so how can we do that well right now we can just change this dummy variable to true and that should show us our sign up now we have the sign up with the first name last name email and password repeat passwords as well and the button says sign up this is extremely good because what beginners in react would do is they would create two different components for the sign up and the sign in they would copy all of this code right here and create two different components what we did is we just created one variable called is sign up and then based on the change of that variable we changed it from sign up the title we added or deleted some fields and we also changed the title of the button you can see in react you have to think reactively one last thing that we could do is we could make a button that's going to allow us to switch from the sign up and the sign in so let's do that right now below our button still inside of the form we're going to have another grid this grid is going to be of a type container and it's going to have a justify property which is going to say a string of flex end inside of there i'm going to create a grid this grid is going to be of a type item and then inside of that grid we're going to have a button and that button is going to have an on click property and on click we're going to call the function called switch mode so that switch mode again is just a function which we're going to declare right there const switch mode it's going to be an arrow function and then in here we're going to switch the mode from the sign up to sign in now what is our button going to say again it's going to be different if we're logged in or not so i'm going to again open this say is sign up if we are on the sign up we're going to say already have an account question mark sign in otherwise we're gonna say something like don't have an account question mark sign up okay let's save that and see how does it look like there we go you can see that we have this button right there but right now it's not doing anything so what do we have to do to actually make this is sign up switchable think about this for a second try implementing this yourself and then once you've figured it out or once you're stuck come back to this video and i'm going to show you how to do it what we have to do to make this work in react fashion is make a new state field i'm going to take this is sign up variable and i'm going to turn it into a state field so i'm going to say const is sign up and set is sign up that is going to be equal to use state and at the start that can be false now we can remove this everything is still got a function but now we have access to this set is sign up and now we can use that inside of our switch mode function so right inside of here we can say set is sign up and what we simply need to do is do the same thing that we did right here for the password since we are using the previous state to manage a new one we have to get a callback function and say prev is sign up and then in here simply say not prev is sign up that's going to switch it on and off like a switch also i want to reset the show password if i switch the mode so i'm going to say right here handle show password and i'm going to pass the value of false let's save it and see if it works we are on the sign in i click it we are on the sign up there we go this works as expected now we have a great looking form as you can see we can go back in here we have all of the posts we can head to the sign in and there we go in here we have the sign in and the sign up form which both look amazing now the login and register using these fields the first name last name email and all of that is going to take a bit longer so what i would want to do first is implement the google login button that way we can first handle the authentication with google and then we'll be able to do everything else that's better because if we first implement google that way we'll still have everything functioning as normal and then later on we'll be able to add everything else including these fields let's add the google sign-in button right here above our current one to do that we'll have to import one thing and that thing is called google login so right below our material ui imports in here we can say import google login from and that is going to be react google login we installed that package at the start of this video okay and now we have to use that google login how do we use it well it's going to be a simple button so right here above our current one i'm going to call that google login as a component and it is going to be a self-closing component and here's a hint for you whenever you're importing something and that something starts with a capital letter most likely it's going to be a component inside of here you have to have your own client google id so this is something that we're going to add as soon as we're done with creating the layout for this so i'm going to say google id we have to put that right there then below we have render render means how are we going to show our button what is it going to look like so in here you get something known as render props and this is a callback function so inside of here you can create a callback function it's not going to have curly braces it's going to be just an instant return and then inside of there we're going to put a normal material ui button that button is going to have a class name of classes dot google button it's going to have a color of primary also it's going to be a full width button and it's going to have an on click listener on click we're going to call the render props dot on click it's also going to have a disabled property and there we're going to put the render props dot disabled and it's also going to have a start icon that start icon we're going to import but it's going to be simply icon a self closing component that's simply going to say icon we're going to have one more thing and that one thing is going to be a variant of contained variant is equal to contain i see that we have quite a lot of things some people prefer to have them like this this way it's more easily noticeable what we have and i agree we can leave it like that for now until we actually finish the button so we have the button and finally what can we say in there we can say google sign in now you can see that we're missing the icon property so we have to import that the icon is going to be a simple svg so we're going to create a new file right there called icon.js and now in here we can paste that icon so this is going to be an svg react component and we can simply import it inside of our auth you can again copy and paste this icon it's going to be linked in the description now inside of our auth we simply have to import that icon we can do that easily by saying import icon from dot slash icon as you can see now we have everything that we need in our button so what i prefer to do is to have it in one row because this way it doesn't clutter our view we know that it's a button it has a bunch of props and it says google sign in okay great now we can continue with adding different props to our google login and these props are going to be on success and also on failure so we have two handlers here the handler for success action and for the failure action on success we're going to call google success function and on failure we're going to call google failure function we're going to create both of these functions finally the last thing that we need is going to be cookie policy and that is going to be equal to single underscore host underscore origin okay now we can create those two functions just above inside of here i'm going to create the arrow function for both of these so i'm going to select them both and say const google success and google failure is equal to an error function and it's going to be a block of code so what do we do on google success and on google failure well on google failure i simply want to console log an error so in here i'm going to say console log google and that's going to be a string google sign in was unsuccessful okay and we can say something like try again later okay so this is going to be our google failure and then what do we want to do on success well in here we get access to a full response so i'm going to say rest here and for now i simply want to console.log that res of course this is not going to work out of the box because we still haven't supplied the google login with our client id so we have to find that to get your own client id you have to head to console.developers.google.com i'm going to put this link down in the description instead of here on the left side you'll have a sidebar that says credentials and then oauth consent screen first we're going to go to oauth consent screen i already have mine created you'll have to create a new all odd consent screen you can name it something like memories app or something similar and then in here we'll have to do a bit of a setup you can create our app name you can put your user support email and then finally you can add your developer contact information and click save and continue with that you created your odd consent screen in this case under scopes i currently have nothing nothing under test users and this is the summary that's it and finally we can go back to the dashboard now that you have the oauth consent screen you can head under credentials inside of the credentials you can click create new credentials and then you can choose odd client id inside of here you can choose the application type and in our case that's going to be a web application i'm going to call it memories app inside of here you can put the localhost 3000 as the uri and we can also do that for the authorized redirect uris so inside of here we can do something like http localhost and let's do three thousand i think that we can also add the forward slash off this one with that said we can create it and i think that should be enough localhost three thousand and localhost three thousand four slash auth for that and there you go you get your oauth client id and the client secret don't forget this site yet we'll have to come back to here once we actually deploy our application because in here you'll have to add a different url because now it works only on our local host okay great so we can copy our client id we can come back to our application and now inside of here we can simply paste that id right in here with that said i'm interested to see what this response is going to be and how does her button look like with so i can close this tab for now and go back to memories project as you can see we have our google sign in button right here looks like it's connected all the way to our front button so what i'm going to do right now is just switch them so i'm going to switch our google login and our normal login button right there so now we have our manual login button on top of our google login and there we go that looks so much better so now the question is if i open the console what is our response going to look like once i click google sign in okay so right now we get redirect uri mismatch that means that we have to go back to our apis and services meaning console.developers.google.com and we have to see if we have set up everything correctly okay inside of here we do see that we have our memories app all odd client so maybe we have to add the localhost 3000 forward slash auth to here as well but you can see that it cannot contain a path or end with that so that's not going to be the solution what about if we add the http right there and not https let's try with that that works so maybe definitely that's the solution let's save it and let's try one more time in our memories app okay if we click the google sign in now as you can see we get this nice window from google but before we go ahead and click anywhere else i just noticed that we have one more thing that we have to do our google success function is going to be asynchronous that means that we have to add an async keyword in front of this function now let's save it go back and now finally let's click that google sign in this is crazy because we didn't code any of this google automatically gave us this window so now i'll try to log in with javascript mastery and take a look at that we got google sign-in was unsuccessful not as i supposed to be but that's normal errors happen so along with this console log google sign-in was unsuccessful i'll also try to console log the error so inside of here we can console.log error okay we got an error right there and i'll try to copy the details and paste them right in here so that we can both see what our google says i'm going to extend this into multiple rows usually you should not share your client's id with everyone but i'm going to delete this after recording the video so it's okay okay so the error says not a valid origin for the client http localhost 3000 has not been whitelisted for client id please go to they give us the url and whitelist origin for your project client id after a bit of googling i found out that the issue was not that we had to add something to our google developers console or something to our code we simply had to clean the cookies so let me show you the solution that they found the solution was in stack overflow and what you simply had to do is clear the browser's cache so in chrome settings advanced clear browsing data cached images and files and that's it that's gonna do the trick so after you do that and come back to the site if you click google sign in take a look right now you can see all the details right here which means our login was successful also while we're here let's get rid of this boring warning it simply says invalid prop input props of type boolean supply to forward draft text field that means that if we go back into our input component right here this is getting a boolean and that means that in this case we cannot use the end end we rather have to use the null because this cannot be a boolean it has to be a null or a specific component so if we save that the error is gone and as we discussed our sign in works beautifully now we have to use some of these details we got right in our response and we can use them right inside of here odd google success now we have access to this entire object so what do we need well we can say const result is equal to res and now we can use the optional chaining operator the question mark dot the question mark dot is a special operator that's not going to throw an error if we don't have access to the rest object because maybe sometimes we're not going to have this rest object so we want to make sure that we don't get an error if we don't have it that way you can say profile i'll be j so now we are not gonna get an error if this doesn't exist before if you use just the dot if the rest object didn't exist then you would get an error saying cannot get property profile obj off undefined because res profile obj would be undefined if you do this it's not going to throw you an error it's simply going to say undefined that's going to be the value of the result great so now we know how the optional chaining operator works and now that i think about it it's kind of crazy that i knew the exact error message that we would get if we didn't use this yeah so with that said let's continue we also want to get the token and we can get the token from res question mark dot token id so now we have the token and we have the result that's basically everything that we need since we are working with an async function we can use the try and catch block so now if our login is successful we want to dispatch something otherwise we're simply going to console.log the error so how do we dispatch something well of course we have to import use dispatch from redux so inside of here i'm going to say import use dispatch and that's going to be coming from react dash redux of course since it's a hook you need to say cons dispatch is equal to use dispatch and finally we can use that dispatch to dispatch an action so we can say this patch call it as a function and now inside of there we can send some data in the type of our action is going to be simply auth and then the data we'll be sending in is going to be the payload and all that we want to send is a new object that contains the result and the token that is going to be it now that we are dispatching this action and we're sending the payload in the only thing we have to do is add reducer that's going to handle it properly so let's go to our reducers folder and then in there we need to create the reducers for the auth so inside of here i'm going to say new file off dot js inside of here as always we need to create a basic reducer so we're going to do the same thing that we did in the post first we need to import some of the constants in this case we're not going to have these what we want to have is going to be the auth and the logout of course these are constants in the action types constants so we can go to this folder action types and now inside of here let's create those export const and that is going to be auth is equal to a string of auth and this one is also going to be logout just to reiterate we are doing this to save ourselves the trouble of accidentally misspelling a variable because that way we wouldn't have the error this way since everything is a variable if we misspell something we are going to get an error okay let's create our reducer const odd reducer reducers are functions more specifically functions that are accepting the state and an action based on that they have a switch case in the switch case we're looking for the action.type in this case it can be something like odd and it can also be logout which we're going to implement later on so if our action type is equal to odd what do we want to do well remember we're getting all the details inside of the action dot payload or more specifically we call the data so let's first try to console.log that to see what are we getting so inside of here i'll try to get action dot data i'm also going to use the question mark because not always is that data gonna be there and that's it let's try to console.log it and see if we're getting it of course we have to export default auth reducer and we also have to use it in the index.js of our reducers so in our index.js we have to import not only the post reducer but also the auth reducer and then we have to use it here in combined reducers and combine the odd as well not to forget we always have to return something so if we don't have any case in here i'm going to return just the old state but in this case we also need to return something so for now until we're just cons logging things i'm going to just return the state and right now our state is undefined so we have to give it a default value so i'm going to say equal to and now i'm going to say odd data is equal to null so if we don't have anything our odd theta of the state is simply going to be set to nothing if we save that let's take a look what do we get okay one more time through the process click google sign in okay and take a look this is our whole thing we have a result in here we have javascript mastery we have our google id and we have our token that's all that we need so what do we do with that well we want to save it in the local storage because that way once we refresh the page the browser is still going to know that we are logged in so to do that we can say local storage dot set item is equal to profile then we want to say json.stringify and then there we want to say dot action question mark data this is it so we are setting all of this that we have all of the data for the login we're setting that to the local storage finally at the end we want to return something we're going to return dot state and then we want to specify the odd data to be equal to action dot data and this action data is also going to use optional chaining so this is it for the auth now that we have this return right there and we are setting our profile with the data field for the user we can try to use it somewhere the best place to use it would be a navbar because in here we already have our user which is currently set to null so now let's try to add a real user in here to do that we can create a new state field and we can do something like user const user and set user and finally in there we can use the use state use state of course has to be imported so inside of here i'm going to import the use state as well as the use effect because we'll need to use that later on now this use effect is going to be a bit different we're immediately going to try to fetch something and that something is going to be the actual user so how do we retrieve something from the local storage we say json.parse localstorage.getitem and then you specify the name of that item in this case it is going to be the profile so this is how we can get the user right here now that we have the user let's try to simply cons a login console.log user i'm going to go back to the browser and refresh the page so currently the user is null because remember last time we didn't save it in the local storage so if i open the application tab and right here refresh you can see we don't have anything in the local storage but now let me try to log in one more time with my google account and there we go we have our complete information now if i go to memories it are we going to get the console log with that profile it is still null if we refresh though it is there and as you can see this automatically filled with javascript mastery and my icon so that is amazing one bad thing is that we had to refresh and manually head back to the localhost 3000 and not the login form so let's re-navigate automatically so we don't have to do it manually we can do that using a use effect inside of here i'm going to use a use effect it's going to accept a callback function and of course it needs to have a dependency array in this use effect we're going to check for the token so we're going to say if token exists user and then question mark dot the optional chaining token so we're checking if the token exists and if it does we're sending it to the token variable then finally later on we're going to check for the json web token here if we do the manual sign up but now we're using google so we don't have to do that but what we can do is we can say set user and set user is equal to again the same thing that thing is going to be our user json.parse localstorage.getitem and finally we have to do one more change in the auth more specifically once we dispatch this we actually have to redirect back to the home so for that we can use history dot push like this and where do we push to we push to forward slash history belongs to react router dom so we have to import that import use history from react router dom and then right in here we need to say const history is equal to use history and call it of course okay so now this should redirect us immediately to the home page once we log in let's try to log out oh our logout doesn't work right now but if we head manually to forward slash auth there we go and we can click google sign in once that is done as you saw we were automatically redirected the thing that would make sense to do right now is to simply do the logout so that's going to be our next step to implement the logout we of course have to find where this button is and as you can see it is in the nav bar so if we go right here let's find that button logout and we're going to add an on click listener what are we going to do on the on click we're simply going to log out that logout is going to be one function inside of this nav bar more specifically const logout is equal to an arrow function and what are we going to do we're going to dispatch an action so we have to first import use dispatch from react redux and then in here at the top we need to say const dispatch is equal to use dispatch there we go now in the log out what we can simply say is dispatch and we're dispatching an action that has a type of we can do just a string of log out and that's going to be it once we log out we also want to redirect to the main route so i'm going to say history dot push and also we have to import that history so at the top we're going to say import use history from that's going to be react router dom i see that we already have it so i'm going to move the import right here and how do we get it well cons history is equal to use history so once somebody logs out we're going to push them to the root route to the home there we go what do we also have to do is we have to set the user equal to null so if somebody is logged out the user has to be null okay and i think with that right now we don't even need this use effect we're going to need that for the json web token so i'm going to comment that out and let's see if our flow now completely works so we're right there i'm going to refresh the page i logged out there we go we are logged out i'll check the application tab looks like we still have our profile there and as you can see if we refresh it comes back that means that we haven't fully implemented the logout dispatch so we need to go to reducers off and then in here we have to do something if we log out more specifically it is going to be really simple if we have the logout case like this then what we have to do is say localstorage.clear this is going to completely clear the entire local storage and what we want to return well the same thing that we're turning right here except the odd data is going to stay null okay great so now if we go back refresh the page we have our javascript mastery there i'm going to click log out as you can see the console was cleared and if i refresh there we go our user is still logged out now let's try to go to the whole process of signing in go here sign in using google there we go we are logged in and as you can see our profile is populated and when we refresh we get this javascript mastery i don't like that we had to refresh to get the user who's logged in name so we have to go back and looks like that in the nav bar which is right here we still need that use effect so i'm going to add that use effect so when do we want to call this use effect as soon as the url changes from the forward slash auth to the simply forward slash and we can use the property use location from react router dom we need to do the same thing const location is equal to use location and based on this we'll have access to that change when this changes we want to simply call the user when location changes i can put that right here when location changes simply set the user now let's take a look if that's going to work if i go back log out one more time log in and there we go now we immediately got this user right there because we automatically set the user profile once we came back from the forward slash auth and it was populated amazing and now if you refresh the page go back go somewhere else you're still going to be logged in for i think about an hour because our token lasts for about an hour or if you want to manually log out you can simply do that right away crazy how simple the google all aud system is right we implemented this in a really short amount of time next step is to implement the manual login and registration system using the json web token for that we're going to use this form that we created let's start working on that i'm going to close all of these files just so we have a clean working environment i'm also going to collapse all the files and folders so this is now going to be a first time in this video that we are going to focus on the back end as well because we have to create the models for the user as well as the controllers and the routes for the login and registration for now let's handle the client side of the authentication system to do that we have to go to our odd form right inside of here and now remember whenever you're working on something take a look at the actual jsx and then ask yourself when is this happening and the answer is our login and registration is happening after the user clicks this button that means that we have to focus to implement actions once this button is clicked going back to here we can see that our button is right here if you take a closer look at this button you can see that once you click it it is of type submit that means that the only thing it does is it calls this on submit function in this case the on submit function is the handle submit so let's see where is that and there we go it's right in here more specifically it is empty so we're not doing anything with it right now now what do we have to do with it to make our login work first thing to do would be to check if we have access to all of the state fields more specifically are the values of these inputs in the state and right now we cannot see that we are mentioning state nowhere right and while we're here i also noticed that this should be last name and also in here a last name yeah so we are never ever mentioning state so how can we do that well let's create a new state field right inside of here const and we can call it something like form data form data set form data and that is going to be equal to use state of course we have to make this use state at the start be equal to something so just at the top of our component let's create a new field const initial state is going to be equal to and now in here we have to put the initial values for all of the state fields that is going to be for example the first name which is going to be equal to an empty string then we have the last name also equal to an empty string we have the email again everything is going to be an empty string we have the password and we have the confirm password also equal to an empty string and that is going to be it for our initial state now how do we use it well you simply put it in here that is going to be the initial state of the form data okay now let's try to console.log the form data on submit and obviously immediately considering that we are never setting form data we expect that to be empty so let's take a look if we go back in here if i type something and if i type a password i'm going to open up the console right here and click sign in and first of all it immediately refreshed that's because it is the default behavior of the browser to refresh on form submit so we have to add the event in here we get the event e dot prevent default that is something that you always add on the form submit in react because there we don't prefer reloads we always want to have something on the screen so with that said let's see if we get something there i'm going to type the same thing one more time and click sign in and as we expected we got all of the fields there because that is our initial state but they are all an empty string now the question is how can we populate these fields and the easy answer is to look just a bit below our handle submit we have to handle change and each one of our inputs is using that handle change but right now it is empty so what do we have to do to fill it well in here we get the actual event and then what we can do is say set form data we get an object right we spread the form dot form data and then we update only a specific input that we're currently managing and the question is how can we know on which input are we currently well each one of the inputs has its own name first of all you have to make sure that your names are exactly the same as the names in the initial state right here first name last name email password confirm password and so on if that's the case you can use these square brackets right there and say e dot target dot name and that's going to be equal to e dot target dot value this is going to make sure to spread all of the other properties but only change the one specific one you're currently on with the target value that means the current input that we have in there with that said if we save that let's try one more time and see what do we have in this form so i'll first try to enter something and there we go we have our email and we have our password if i switch to here we have our first name and if i click sign up there we go we have all of our values listed right in here so that's why we had to use the same handle change function for each one because otherwise because otherwise you would have to change each state field separately which is quite a lot of code this way it is a lot easier this is dynamic and works for infinite number of fields with that said that's great now we have our handle submit but the question is what do we want to do on that submit well they're going to be two different types of submits one is going to be our sign up and the other one is going to be our sign in so we already have a variable to check that so we can say if is sign up in that case we want to do the logic to sign up the user else if we're not on the sign up we want to do the logic to sign in the user so in this case what we want to do is we want to dispatch an action and more specifically that is going to be a sign up action and to that action we want to pass in the entire form data and we also want to pass the history we pass the form data so well we can have it in our database of course but we pass the history object so that we can navigate once something happens okay great and the other one we can copy this and simply put it right there this one is going to be sign in all of these are actions that we have to import first so just above i'm going to import these two actions inside of here i'm going to say import sign in and sign up and that's going to be from dot dot slash dot slash actions and then auth this file doesn't exist yet but we're going to create it right now okay so if we save that we're ready to start creating the actions file that's going to be inside of the actions and we simply need to do auth.js inside of here we can start creating our odd actions first of all we're going to need some things from here like constants action types and all the things from the api so let's copy these and simply paste them right here in this case we won't need those the ones that we need is simply going to be auth and from the api later on we're gonna use some of the calls but right now we don't need anything so let's start with creating the actions while we're creating them we can also export them that's gonna mean export const and we named it sign in that is going to be an action creator which is a function that simply returns an action and as we discussed in the last video if actions or more specifically action creators are asynchronous then we have to use redux tank meaning we have a function that returns an async function with a dispatch i know it's a crazy syntax but we just have to follow the rules in this case so we have this and then we have async dispatch function which then has a function block in here we get what we passed into our function so we passed the form data and we passed in the history so we can repeat that here form data and history if we're in an async block of code we can use the try and catch and now in here we can do the logic if you remember what we were doing in the posts actions you can see that in here we were trying to fetch some of the things from the database and that's going to be the same thing that we're going to do right in here in here we're going to try to get the data for the sign in or rather we're going to send the data to the database or to the backend so that it knows to sign in the user right now we don't have the backend endpoints for this to actually work so this is going to be a good time to transfer back to the backend before we do that though let's just create a complete mock of the sign in and the sign up and then we'll move to the back end so for now in here i'm just gonna say log in the user and then finally why do we have that history because we want to navigate to the home page so that means that we can do history dot push and then simply push the slash after we log in the user we push to the home page and then in the catch for now we can simply console log the error okay and now i'm going to copy this and do the same thing for the sign up i'm going to just rename this to sign up we also get the form data and the history we get the dispatch and in this case we need to sign up the user and then finally we navigate to the home page and console log the error and now we're pretty much done with the front-end side for now of course later on on the back end while we create those end points then in here we'll be able to call them but for now there's not really a lot we can do on the front-end side now we need to move to the back end create the user model create the controllers and the routes and then we'll be able to continue so let's do that as before i closed all the windows collapsed the folders and let's start with the back end we can focus on the routes first more specifically in the index.js we need to add the routes for the users so instead of here i'm gonna say app.use we're gonna use the user endpoint and then in that case we're gonna have the routes called user routes those user routes as you can see they're undefined yet but we have to import them as we imported the post routes so i'm going to copy this line and just change this to user routes and that's going to be coming from that slash routes and users.js now we know that we have to create the routes right inside of here users.js so how are these routes going to look like well first we have to have the basic structure as we already have with this thing we have to import express from express then we have to get some of the controllers from our controllers right now we don't have any then we have to create the instance of a router and finally we have to export the folder router before we export the router we of course have to add those routes and you add them in the following manner router that and this is going to be a post route to forward slash sign in why is this a post route because you have to send some data to the back end more specifically you have to send all of the details from the form to the backend the form sign in and sign up is the best way to explain how does the post request work you need it to be a post request because you have to send all of the information from the login form to the backend and then and then back and does something based on that information in this case it's going to sign in the user so what are we going to do when we go to the sign in well we're going to call our sign in controller and i'm going to copy this one more time we have the sign up as well and this is going to be sign up obviously these are undefined right now so let's import them from here sign in and also sign up of course these are not coming from the posts they will be coming from user.js of controllers so in here we can create user.js of controllers and this is going to be the place where we're going to put all the complex logic of actually signing in and signing up the user in this file we're going to need a few things first we're gonna need a package called bcrypt bcrypt is used to hash the password of course if you're creating your users users want to have some security if your database is hacked and if you're storing your passwords in a plain text everybody will be able to see it if you hash the passwords that won't be the case that's why we use bcrypt we can say import bcrypt from bcrypt js like this and we also need jwt jwt stands for json web token and that is a safe way for us to store the users or more specifically store the user in a browser for some period of time for example for an hour 2 hour or even a week that way if user leaves the site he will still be able to stay logged in no matter what in this file we have to use the user model which we haven't created yet so now would be a good time to create the user model inside of here i'm going to create a user.js file that is inside of the models now the situation is going to be similar to what we have with the post message we have to import mongoose we have to create a schema and finally we have to create a model which we then export so let's repeat the process import mongoose from mongoose then const user schema is equal to mongoose.schema make sure to put the capital s right here and there we have an object now inside of that object you put all of the necessary details we have a name and name is going to be required so inside of here we can say name type is going to be of a string and required is going to be set to true then we have an email email is also going to be of a type string and required is going to be set to true we have a password password is also going to be of a type string and the required is going to be set to true and then we have the id id is going to have a type of string and that is going to be it for this user schema finally we can say export default mongoose dot model you need to specify the user model with a capital u and you need to specify a schema on which that model is built upon and in this case that is going to be the user schema now in the controllers we can import that model the user model and then based on that we can create a lot of instances of users our memories learn project users so for that we can say import user from dot slash models slash user dot js and now we can create our controllers we know that we need to have two one is going to be export const sign in and that is going to be an async function on all of the controllers we have the rec and the res which is the request and the response and we have a function block this is going to be the function for the sign in and i'm going to copy this and simply replicate it for the sign up so now the question is how does the logic for the sign in and the signup look like that could be a complex part right well both yes and no it can be daunting if you're just starting with it or if you're trying to build this yourself for the first time but in this case you're watching this tutorial and i'll try to be as thorough as possible and guide you step by step through how to do this usually all sign in sign up projects are similar in any application you need to have a sign in system so once you know how to do this once you'll be able to mostly duplicate the code and achieve the same purpose in any app that you build first of all for the sign in we're going to get two things from the front end and those things are going to be the email and the password so the question is how are we getting it from the front end whenever you have a post request you get all the data through the request.body we can say const and then the structure the email and the password from rec.body so we're destructing that all the post data that you send is going to be available for you in direct.body okay now that we have these values what do we do well we are in an async block so i'm going to open a try and catch if we are signing in we first have to find the old user right so i can say const old or we can better say existing user existing user and that is going to be equal to a weight user dot find one and we find the user by email that means that we are searching for the existing user in the database because if you're signing in we cannot simply create a new one we need to find the old one already existing in the database in this case we're gonna say if no existing user then we're going to simply return rest.status 404 because it means we cannot find it and then dot json the message is going to be equal to user doesn't exist that is it that's if we don't have the existing user in the database if that is not the case we have to check if the password is correct so if the new password that user typed in is the same one to the password used when he or she initially created the account we can say cons is password correct and that is going to be equal to await decrypt dot compare and what we want to compare is the password to existing user dot password we cannot simply do a normal string check because before or rather later when we implement the b bcrypt we're going to hash the password so we still have to use bcrypt to compare the hashed passwords and see if they're the same then we can do one more check and say if no is password correct so if the password is not correct return res dot status that's going to be 400 dot json and in there we're going to have a message and what we can say is simply invalid credentials okay that's that's good and moving on if the user already exists in the database and if the password is correct then we can finally get his json web token that we need to send to the front end so to do that i'm going to say cons token is equal to jsonwebtoken.sign and in there we have to provide all the information that we want to store in the token in this case we could store the email email is going to be equal to existing user dot email and we also want to keep the id which is going to be equal to existing user dot id or it's going to be dot underscore id don't forget that underscore with the id the second argument to the json web token sign is the secret instead of here you have to have the secret string that only you know usually you would put it in a separate env file where you store all of your variables where nobody else can see in this case we can simply say test right there and that is going to be enough as this is a youtube video i'm trying to keep it as concise as possible if you'd like me to make a separate video of this series where i go through the entire project and just apply all of the best possible programming habits to it like move all of the things that should be saved to somewhere else and refactor the code and so on feel free to let me know in the comments for now we're gonna simply leave this as test finally the last thing is the options object so inside of here one of the options we'll use is expires in and we're going to say expires in one hour just one h and that is going to be it for our token finally now that we have the token the last thing that we have to do is simply return it so we can say rest.status status is going to be equal to 200 and dot json what are we sending we're sending the result which is going to be equal to the existing user or rather the user that's trying to log in and we send over the token that we just created here on the backend if the token creation didn't win successfully we can say rest.status 500 that means an undefined server error and then we can say json and what are we returning well just a message that says something went wrong we don't really have the info on what went wrong and this is it this is our sign in controller of course more important part at least right now is to create a sign up that way we'll be able to add the user to the database so let's add the sign up right now it's going to be quite similar but it's going to have a few distinctive differences again we want to get something from the reg.body rec.body we're destructuring the things that we send over and remember what do we have on the front and side when we are signing up we have first of all the email password and then we have the first name and the last name as well we also have the confirm password field don't forget about that okay so now that we're getting all the data let's start with the logic we again have the try and catch block and in this case we are also going to try to find the existing user so we can say const existing user and this is going to be the same as we had right here so we try to find a user with that email why do we do that if you're signing up think about it we cannot create an account if there already is an existing user so in this case i'm going to copy the same line that we have right there but in this case i'm not going to say if not existing user i'm going to say if existing user that's the problem right there and then what do we want to return res the status that's going to be 400 and we're gonna say user already exists moving forward if we don't have the existing user that means that we're good to go to create an account but we first have to check if the password is the same to the confirmed password so we can say password is equal to confirm password or rather we can say if the password is not equal to to the confirmed password in that case we're going to return the same error right here so i'm going to paste that return and in this case we're going to say passwords don't match that's that means that the user has to re-enter them one more time okay great moving forward if we don't have the existing user and if the passwords match that means that we're good to go to create the user before we create him though we have to hash the password because we don't want to store it in a plain text to do that we can say const hashed password and that's going to be equal to a weight bcrypt dot hash and then in here we simply pass in the password the second thing that you pass is called salt and that is the level of difficulty that you want to use to hash your password people usually use 12. okay so now that we have the hash password we have to create our user i'm gonna say cons result is going to be equal to await user dot create and how do we create a user we have to pass in all the data we pass in the email we pass in the password but take care it's going to be hashed password in this case then we pass the name the name in this case is going to be a template string where we first take the first name and then add a comma and then add a space and then enter the last name so we're gonna combine the first name and the last name together just like this okay now that we created the user we also have to create the token so i'm going to copy this line from above cons token is equal to json wt jsonwebtoken.sign email is going to be equal to result.email and id is going to be equal to result dot underscore id the secret is going to stay the same and expires in is also going to stay the same finally after this is all successful we have to return our user so i'm going to copy the return from the line above and what we can say is rest.status 200 means everything went good and we send the result in this case the user itself is the result and we also send in the token if something went wrong of course in here we can simply send res that status 500 something went wrong and this is it now we have the controllers for the sign in and the sign up this alone should be able to allow us to log in and register i'm really trying to be turo explaining this because i know it's a hard concept i'm really glad we went through this hard part it's definitely not easy so make sure to re-watch it if you don't understand some of the parts if you like my current way of teaching definitely make sure to leave a like and comment it really helps with the youtube algorithm with that said let's move to the second step and that is once the user is actually logged in he can do all kinds of actions he can delete a post that he created he can like it he can like all the other posts and their back end needs to be able to basically say okay you are allowed to do that you a real user you're currently logged in and you can do that for that we use something known as middleware so our next step is going to be creating authentication middleware to create any kind of middleware we can create a middleware folder so right inside of the server we can create a middle where folder you can see if you use some kind of icon theme like material ui icons it's automatically going to get a different look inside of there i'm simply going to say auth.js because the middleware inside of here is going to be for auth right now you might not understand what a middleware means it's a specific name but as soon as we create it i'm going to show you where that piece of the puzzle is gonna fit in as i show you that it's going to make complete sense so for now let's start with the middleware we're gonna import jwt from json web token then we're going to create our odd function so we can say const auth and it's going to be equal to an async function where we have a rec res and the next even by looking at this you can immediately see that our middleware is really similar to what we have on our controllers they all have the wreck and the res but our odd middleware has something known as next that means do something and then move to the next thing again you're going to see it in just a few moments in action but now inside of there we're going to add a try and catch block for the catch we're going to simply cancel log the error for now and now in the try block we have to see if the user is really who he is claiming to be and we can do that using json web token so after the user is signed up or signed in he gets this specific token now when he wants to do something like like a post or delete a post we have to check if his token is valid and that's what we're doing right here so to get the token from the front end we can say cons token is equal to rec dot headers dot authorization dot split so we split it and we only want the token itself and the token is on the first position in the array after we split it then we're gonna have two kinds of tokens we're gonna have the one from the google auth and we're gonna have our own so inside of here we can decide if it is our own or the google auth that's going to be a variable where we're going to say is custom off and if the token dot length is lower than 500 then it means that it is our own if token length is greater than 500 that is going to be google auth then we can create a variable called decoded data so that is the data that we want to get from the token itself and now finally if we have the token and if the token is our own so if it is a custom auth in that case we want to set the decoded data to be equal to jsonwebtoken.verify this is going to give us the data from each specific token it's going to give us the username of the person and its id inside of here we have to pass the token and we need to have that secret we were talking about in this case we know that the secret is test it has to be the same secret you used when you were creating that specific token you can see right here we use test and in here we use test and now that we have the decoded data we know which user is logged in and which user is for example liking the post or deleting the post so we're going to store his id in direct.user id so reg.user id is going to be equal to decoded data question mark dot for the optional chaining id okay this is how we get the user's id if we are working with our own token and if you're working with the google's or token we're gonna do the same thing decoded data is going to be equal to json web token dot decode in this case it's going to be the code and simply pass in the token in this case we don't need the secret once we have that the situation is going to be similar rec dot user id is equal to decoded data question mark dot and in this case we're going to say something known as sub sub is simply google's name for a specific id that differentiates every single google user basically it's an id that we can differentiate the users with finally we can call the next so that we can pass the action onto the second thing for example if the user wanted to like a post so let's say a user went and he wants to like a post wants to like a post he has to do this click the like button and then this is what happens first we don't immediately like it because we are not sure if he has permissions to like it first we go through the odd middleware okay auth middleware confirms or denies that request so if all this is correct we're going to call the next and we're going to say okay you're okay to like that post so if odd middleware says okay you're good to go only then are we going to call the like controller and this is what middleware is for for any kind of action that happens before something this next thing is crucial we are saying do this and then do something next do something after this is done and that is a middleware okay with that said we can finally export default auth now the question is where do we use that auth middleware and the answer is in the routes for example we said when somebody likes something in that case we want to use that middleware so first of all let's import it import auth from dot slash middleware slash auth and we are on the back end so we have to do the odd.js okay this is going to be our middleware now we want to add it before specific actions for example all of the users no matter if they're logged in or not they can see all the posts but to create a post you need to have your own id you need to be logged in then in this case i noticed that this is an extra action that we don't need so we can delete this one because we don't have a specific memory page we can implement that in one of the future videos then we have the edit post or update post in there we definitely need to have the auth happening before because we need to see if the user has the permission to update a post same thing happens for deletion do we have the right to delete that post and finally the same thing happens for liking why although everybody has the permission to like something he cannot like twice or three times that's why we need to call the odd before to have the specific user's id and he can only like once for that specific id great now you know how to create auth and also where to add it now the majority of our back-end work is done but we still have to implement the logic for for example liking only one specific post right now you can like as many times as you want we also need to implement the logic for deleting only the post that you created or same for updating the posts only you created you cannot simply update or delete any post that's there and that's going to be it this one the like post is going to be managed on the backend and if i'm not mistaken the delete post and update post are going to be managed on the front end because what we have to do to disable user from deleting something well if he's not the creator of the post simply remove the delete button it's not going to even be there he won't be able to click it there we go so while we're in the back end we're going to focus on completing it so now our next step is to implement the like post only a single one and then we're going to move to the front end to finalize the things with the auth and with the update and delete post starting with the light controller that's the one that we created in the last video inside of the post js of controllers if you scroll a bit down you should see a like post controller now we have to modify it so that the users can only like the post once so let's do that first of all we have to see if a user is even authenticated we can do that because now we have that special value and that is rec dot user id this is really really important to mention if you call a middleware like this before a specific action like in this case then you can populate the request and then you'll have access to that request right into the next action that you have so if we go into our auth and then in here if we populate the request.userid then we go to the next controller in the row which is going to be the like post and now the request is going to have that user id property with this we can check something we can say if no rec.user id that means that the user is not authenticated and we can simply say return res.json and then message is going to be equal to on authenticated in here we have the same old check to see if we do have the post that the user wants to like then we get the actual post and now we have to see if the user's id is already in the like section or is it not so we can say const index is equal to post dot likes dot find index inside of here we have a callback function where we loop through all the ids so each like is going to be the id from a specific person that's how we're going to know who liked the specific post and what we have to do is we have to say if id is equal to we have to convert his user id to a string and then we can say if the id is equal to string of rec.user id if that is the case that means that his id is already in there that means that that person already liked the post and this is going to be a dislike and not the like so how do we do that we can say if index is triple equal to -1 only if his id is not in here only then is this going to be equal to -1 so this is if he wants to like the post else we're gonna get the index of his specific like in that case we want to delete his like or rather dislike a post great so what is going to be the logic for adding the like that is going to be really simple post dot likes dot push rec dot user id we're basically just pushing his id and if we want to remove his like we need to remove his id from the likes array that's going to be like this pose.likes is equal to post dot likes dot filter our filter accepts a callback function and it's going to loop through all the ids you can see likes are going to be ids and then in here we have to filter out the like from the current person we can do that by saying id is not equal to string of rec.user id and this is simply going to return us the array of all the likes besides the current person's like now that we have the current number of likes we are going to create the updated post and that is going to be the same as we have it here post message that find by id and update but in this case we're not going to update only the likes or the like count we don't have that anymore we're simply going to create a new post so the post that we had we're going to update it because now we have the same old post that now includes the like itself one more thing that we have to do is add the actual likes to each post that is going to be in the post message model right here so far what we had was the like count we no longer have the like count we're going to have likes the array of likes inside of there the type is actually going to be an array of strings this is how we write that so the array of ids and then the default value is going to be an empty array great now this is done make sure to save all the files and now we will be able to go to the front-end part and see if we can make the calls to the sign in and the sign up routes and controllers this is the thing with back-end if you work with the back end most likely you have to write a lot of things and not visually see something that's just how it is with the back end but now we're going to move back to the front end since we're building a full stack app and we will be able to see the logic that we implemented on the back end i closed all the windows just so it's easier for us to go back to the front end and let's focus on important things inside of our actions more specifically aud actions we said that we need to log in the user but at the time we didn't have the actual endpoints on the back end that we needed to contact now we do have them so that is our next step to log in or to sign up the user for that we're first going to create api endpoints like we did for all of our actions with the posts now we need to create these only for the authentication before we start with that we're first going to do some updates to our current setup i'm going to create an axios instance const api and that is going to be equal to axios dot create inside of here we can create a base url so you can put options like this an empty object and then inside of there you can specify the base url now we're going to set the base url to be a string of http forward slash localhost and then 5000 just like so we don't want to have that for slash posts because now we're going to have the api also to make some different calls for example to the users and not only to the posts now we can delete this and now instead of two axios we'll be making all of our requests to the uppercase api this is going to do the same thing absolutely the same thing but now you don't have to specify the starting part of this url so how do you change that well now it's not going to be api.get forward slash url it is simply going to be forward slash posts we always have to add that in this case we also want to reach out to something like forward slash posts that's the same in this case it is going to be forward slash post and then forward slash id and then forward slash like post in this case posts only forward slash post and in this case also posts we already have the id we did that so that later on we can use some more advanced features of axios some of the features of the not often mentioned in easy tutorials and are definitely a good thing to know before that though let's simply create the routes for the sign in and the sign up export const sign in that is going to be an error function and that arrow function is going to accept the form data so what do we call once we make that request api.post and that's going to be a post request to forward slash users forward slash sign in finally as the post payload we want to send the form data i'm going to replicate this request and we're just going to rename it to sign up right here and we also have to rename it right here sign up everything else should be the same with that said we can go back to our actions right here and now we have those api calls the sign in and the sign up so what we can do is we can say const destructure the data from our request and make that equal to a weight api dot sign in of course we have to pass the form data and i know this redux flow can be confusing like we have this form data here we have it in the api then we're passing it from here where is that coming from where is that going to how do we get the reducers i know that can be confusing so one more time let me give you the whole explanation of the redux workflow first we get to the actual form the form is a component right here in the auth once we fill in all the inputs we want to dispatch something this patch immediately has something to do with redux we are dispatching an action this action is called sign up for example let's do sign in in this case so we're dispatching a sign in action and we're giving it two different things the form data and the history once we dispatch that we come to our actions and that is this thing we're dispatching this whole action now this action makes another call to our api just so we know where we're going and it's basically this it makes a post request says hey database get me some data and return it to me and we write in our action that's what we do we get some data and we get it right there finally from our action creator we can finally dispatch some things and then we're coming into our reducers so in this case once we have the data we want to dispatch an action with a type of auth and we want to pass over the data to our reducer now we're going to repeat the same process for the sign up it is identical so in here we get the same thing but we change this from sign in to sign up and with that our odd actions are done now we have to see if our odd reducers are also done inside of here we're getting the profile and then we're setting it to the local storage so this part also seems to be done for now to check if it works i'm gonna save all the files and go back to the browser okay once we are here for now we cannot see the posts but that's okay let's try to sign up inside of here we have to sign in but let's first create an account let's do something like john wick and that is going to be john wick gmail.com the password is going to be one two three one two three first of all obviously something is wrong right there because our input is not hidden it's not a password and then our repeat password looks okay so let's go ahead and check what's wrong with that why don't we have our password that is going to be in the auth more specifically in the password field so that should be right here so if the show password is true then set that to text otherwise show that to password okay that seems to be great but maybe our show password is wrong so let's check the show password show password by default should be set to false and it is so where does the error seem to be let's check that out well one thing that i can notice is that in here in the switch mode we're calling handle show password and setting that to false we simply should have called the set show password and set that to false so inside of here i'm going to change this to set show password let's save that and see if it makes a difference okay now it's good but i still don't see that icon on the right side that lets me toggle this thing so let's see what is wrong with that so if i go back right there and that's going to be inside of our input component so i'm going to head there let's see so if name is equal to password oh there we go password what is a password javascript doesn't know that so obviously we have to make this password now if we save that let's see if that is going to make a difference there we go now we have this nice icon we can we can again go as john wick john wick one two three one two three let's see if we made a mistake we haven't that's really good and finally repeat password one two three one two three now i'm going to collapse this i'm going to clear the console and go to the application tab in here let's see if our local storage is going to be populated with our newly created profile i'm going to click sign up right now and looks like something did not work and don't worry i just wanted to show you that this is the thing that usually happens remember for the past half an hour or so we worked on the back end solely we didn't check for mistakes we didn't see if anything goes wrong we just went ahead and tested it usually when you change something for a bigger amount of time it's not going to work the first time you test it that's just what i wanted to show you so right now we have 404 and looks like it's just psy up so it's just one more typo and this is going to be happening on the front-end side i think so if i go back to the code to our api there we go sign up so we're just missing that n right here with that changed let's try to make another request john wick again john wick one two three one two three and let's test it out again i'm going to open the application tab to see if our local storage is going to get populated sign up and again we have an error sign up not found localhost 5000 forward slash users forward slash sign up okay so now i see that we are making a request to the correct route localhost 5000 forward slash users forward slash sign up let's see what seems to be the problem i think that on the back end in our routes more specifically in the index.js of the server we said user not users so again it's just a small typo where you have to be really concise with the routes on the back end and the routes on the front end so now that i change this to user it should work right now again john wick one two three one two three and let's test it out okay there we go looks like we are logged in we have our j right there john wick and let's open the application tab and would you look at that we have our email we have our name our password which is now hashed take a look at this this is not one two three one three this is a complete hash of the password and finally we have the backend generated token which stores all the information about the user so now if i refresh the page the user shouldn't be logged out and there we go he is not he is still here finally can we log out the answer is yes we can and to test our sign in let's go with john wick one more time one two three one two three and test it out okay with the sign in we again got a warning or an error saying user okay it looks like i'm missing the end right there you guys are sure seeing this and are like oh you missed the end there so okay now we have it now we should be able to sign in one more time and let's do it there we have it we successfully created the account stored it in the database registered and logged in and the login is also persistent you can refresh all the way you want the user is still going to be signed in for an hour or until he presses log out now our next step is to check if the user can do all of the user actions like creating a post or deleting a post or maybe liking some posts so that's going to be our next step before we check for all of these actions though there's one more thing that we have to do and that is going to be in the api remember how i told you that we created this axios instance so that we can add one more thing to it and that one thing is going to help our odd middleware our middleware cannot work without that one thing and that thing is adding something specific to each one of our requests how do we do that we can say api dot interceptors and dot request this is going to be a function that's going to happen on each one of our requests so in here we can say dot use and then you provide a callback function that callback function gets a request as the first parameter so again this is going to happen before all of these requests so why do we need this because we have to send our token back to our backend so that the backend middleware can verify that we are actually logged in for that we can say if localstorage.getitem and want to get the item of profile that's where we store the token so if that exists then we want to add something to our request and that something is going to be rec dot headers dot authorization just like this remember if we go to the back end and take a look at our middleware right here you can see that we're taking something from rec.headers.authorization and now they look at it this must be uppercased great so now let's take a look wreck.headers.authorization in here we need to put our token and the token is going to be a string and it needs to start with the word bearer so this is going to be a bearer token the first thing is the bearer just a string and then the second thing divided by a space is the actual token we can get that by saying json.parse inside of there we get the local storage dot get item we get the profile and then finally if i can close this correctly on that profile we need to say dot token like this so we want to get the token from that specific profile it looks like i'm missing something no that seems to be it so we're adding the bearer prepending that string to our token and now we're adding that to each and every request finally with interceptors we have to return the actual request so that we can make all these future requests with that our backend will be able to get a specific header and then based on that header we can do what we've done here decode the data and based on that our backend is going to know that our user is indeed logged in so for the user creation now that we have this rack user id on the back end we can head to controllers and posts we've dealt with the like post but we also have to make a change to our create post right here so you can find that create post controller in the post.js controllers and that in here we can make some changes inside of here we don't have to take all of these values because they are just one thing they are the entire post so we want to have the entire post and then we set the new post message to be equal to new post message instead of here we're going to have the entire post so what we can do is first of all spread the values of a specific post and then this is the key part we want to set the creator of the post so creator to be equal to rec dot user id so now our backend automatically specifies the creator of a specific post and then we also want to add a created add property so created add and created that we can set that to be equal to new date call that as a function and then put dot to iso string this is going to make sure that our date definitely shows the value when it was created so these were some of the changes that we had to make to this create post but now that we change this now our creator is no longer going to be the name that we ourself specify it is going to be an id that means that we have to go to our post message model right there and now along with the creator we need to add one more thing and that is going to be a name so we still want to have the name but it is going to be the name of the person who is logged in not something that we can type ourselves before we had to type in our name because we didn't have the login but now we do and that is a great thing i understand that some of these changes are really hard to get a good grasp on if your first time building this thing like what is even json web token how does that relate to middleware and why are we adding headers and a token each time that we send the request from the front end these things can definitely be dawn thing so if you're having some troubles understanding definitely make sure to rewind some of the parts of the video and re-watch them but still one more time i'm going to make sure to go through the whole workflow to explain what's happening this time i'll show all of that in the browser's console so one more time i'll go back right here and we're going to open our network tab i'm going to be looking at the requests that we've made from our front end to the back end before we do that i forgot to remove this creator right here we don't need that anymore so let's change that in our code that is going to be in the form right here so inside of the form we have to remove that creator variable we can completely remove it since we don't need that anymore and are there some other changes yeah we have to remove it from here set both data and is there something else that we want to change yep we have the creator right here as well so we want to delete that okay now we remove that name but how is our backend going to know what name do we use well what you can do is right in here when you're sending that specific user you can add it so if you dispatch a creation right here we can specify the pose data so we can create a new object we can spread the post data so this is not going to change anything that we had so far but now we can add a name property and name is going to be equal to the users that's currently logged in and that user is going to be stored in the local storage so how do we get the user you can say const user is equal to json.parse and then local storage dot get item and then in there you put a string of profile this is going to make sure to grab the user for you now in here we can say user question mark dot that's checking if we currently have the user and then result question mark dot and finally in here is the name of the user all of that is going to be equal to a name if somebody is changing this we also want to keep his username so in this case we're also going to do the same thing create an object spread the post data and finally set the name to be equal to user.result.name one more thing that we can do in here is check if there is no current to logged in users in that case we want to show a card that says no you cannot create a post right now so let's do that if no user question mark dot result question mark dot name in that case we want to return something and that something is going to be a paper like we're wrapping something in paper like our form is wrapped that paper is going to have a class name of classes dot paper and then inside of here we're gonna simply add one typography that typography is going to be of a variant h6 and it is going to have a line equal to center in there i'm gonna type please sign in to create your own memories and like others memories now we can save that and i think that's going to be it with our form let's go back and test it out now we have the title message everything else is the same okay you can head to the network tab and you can clear it now we're going to be looking at the requests that we are making from the front end to the back end again title is going to be something like new year message is going to be happy new year and by the way guys i really wish you a happy new year a wonderful one a productive one have fun enjoy it and i wish it's definitely going to be better than the previous one okay now let's add the tags you know how people do the tax new year happy new year and also let's do 2021 finally i'm going to select an image let's do fireworks and let's submit it there we go you can see that we have 204 requests right here 204 is not good you can see that our post wasn't created but let's open it and see what's in there so 204 means that it didn't went right but let's see what happened in here we can see that we don't have headers at least i don't see them request headers we don't have the headers for the specific token yep they're definitely missing so let me open the application tab and let's see here in the result do we have our token we do it is right in here but for some reason this token wasn't added to our request okay so in this first one we do have all the information from the request payload we have the tags title selected file and the message but in the second request we don't have anything we have to figure out why the post wasn't made on the back end and if we open our code more specifically our terminal we should get some kind of an error from the back end and we do it is right in here cannot read properties split of undefined add auth that is happening on the back end more specifically in the middleware right here it's saying that it cannot read properties split off undefined that means that direct.headers wasn't sent so one more time in here i'm going to console.log this time just the rec.headers to see if you're getting absolutely any headers from the front end i'm going to go back and just type some gibberish right here test this test and click submit let's see if this times the headers are being sent looks like they're not if i go back we get the same error again but we do see some headers right there the question is is do we have the authorization and looks like there it is authorization bearer token is right in here so that is good we have them oh but here's the thing first time that i wrote authorization it was correct with lowercase letter no matter how you write it at the front end at the back end it is always going to receive as the lowercase key letter okay so now that this is done there is one more thing that we have to do and that is exchange the creator for name in our post that is going to be right here inside of posts and then post before creator was the name of our person but now it's not going to be the creator it is going to be simply name we change that the creator is now the id of the person who is creating it with that said we can collapse our terminal and potentially go back and try one more time let's go with new year one more time happy new year and in here i'm just gonna do holidays now we're gonna add the fireworks image and let's see our request there we go john wick's name was immediately populated the timestamp is correct a few seconds ago hashtags are here title is here and everything is here if we take a look in here we get 201 created and we get all of the information for our specific post this is great that means the user can successfully create posts right now you can see that our user also has the edit button and the delete button we still haven't changed those for non-locked end user that's going to be the next step and and we also have the like button and now if we log out take a look please sign in to create your own memories and like other people's memories so right now we cannot create new ones if we're not signed in of course the edit delete and like shouldn't be here as well because if you're not logged in you shouldn't be able to do those actions okay so now let's log back in as john wick and let's see if they can like delete and edit these posts we can start with like and looks like our like action is dispatched as you can see that right here on the network tab we have 200 and the like was indeed added under likes and if we remove it let's take a look yeah it was removed that means that the backend for likes works completely but on the front end we are not seeing the changed as you can see we only have the like we don't see the number of likes that we have so that is going to be our next step of course we are seeing likes under the post and post is this component post.js inside of here somewhere we need to have the button to like something and it is indeed here just like and then we have the like count but considering the like count doesn't exist anymore it's not showing it so how do we fix that well this is going to be a bit tougher because you know how it goes with likes like if you have one like and how it goes with grammar at all you have one like but then there are two likes and then three likes and then if you like something but other people don't like something you have to have a different message so to show all of these likes and like and different buttons depending on if you liked something or didn't like something i'm going to create a new let's call it a sub component of the post component it is going to be called likes the logic for creating the likes sub component is going to be incredibly simple but you have to write a lot of code to get it right because you have to check for a lot of things so what i'm going to do is i'm simply going to give you the logic for that right here i'm going to paste it because it would take us quite some time to actually go through everything and see what do we have so just to go over it we are first checking if a current person likes something or if it didn't like something we can check that in two ways we're checking if the likes array contains the id of the current person and that can be either the google id if the person did the all auth or it can be a custom id from the database if that is the case we want to say you and a certain number of people like something or the post has one like or multiple likes you can see the s there and then if the person didn't like it we can just say the number of like or likes and so on and then if nothing happened if you're the first to like it it's just like so a lot of things happening here but again just wanted to give you a bit of code so you don't have to write this by hand because really it's not complicated logic it is really simple but it takes some time to write correctly okay with that said you can see that we're missing the user right there and the user is just coming from the local storage for example we're getting the user from the form so you can copy that line it is just going to be const user is equal to json.parts local storage get item and then profile finally now that we have that we can put those likes right inside of our like button i'll try to expand it into multiple lines like this we currently have this but now we have the button i'm also going to add a disabled property so if we don't have the currently logged in user i'm going to say disabled and it's going to be disabled if there is no user question mark dot result so if there is no user we cannot press the button okay and now inside of that button we're simply going to have our new component which is called likes this should solve all of our troubles with viewing the likes great let's check it out if i go back you can see we have one like and it seems liked if i click it again it says nothing it just says like it doesn't say zero likes it's not blue you can see it's just outlined and it just says like if i like it and if i log out now and try to sign in as a different person for example i'm gonna go here and go with javascript mastery this time you can see it's one like it's only outlined if i click it it's now two likes so that looks really good it is like facebook has it if more than two people like this i think it's gonna say you and three others or five others or 100 others so this is really good with that said we can move on to the next thing and that is happening right now as we logged in with javascript mastery as you can see we didn't create this post of course we can like it sure but we shouldn't be able to delete it or edit it and now the delete and edit buttons are right here so we have to disable that from happening let's go back to our post and move those buttons away inside of here what we have to do is we have to check if the current post was created from the current user only in that case do we want to show the current delete button so to do that i'm going to open the logic block and then inside of there i'm going to write some parentheses i'm going to check if user question mark dot result question mark dot google id we already have that so we're checking if the id is equal to post question mark dot creator so we're checking if the currently logged in user via google has the same id as the creator of the post or there is a second possibility if the user question mark dot result question mark dot underscore ib if that is equal to post question mark dot creator so now we're checking if the google logged in user or if our manually logged in user is the creator of this post only if that is the case then we want to show the delete button so to do that we can do what we learned and end and then in here we put the button this is going to now appear only if the logged in person is the post creator if we go back let's see if that works and there we go the delete button is now well deleted let's try to do the same thing for the edit remember the edit is hidden right here in the top right if we go back you can essentially just copy this line the line 52 for me now and we're going to put it above our overlay so right here what you have to do is simply close it down here this is also going to make the button for the edit show up only if the creator is the currently logged in user go back and edit button is gone now i'll log out go back in sign in as john wick and let's test it out there we go our delete button is here and our edit button is here that works perfectly if i'm not mistaken to make this app complete there's only one more step that we have to do and that is check if the token has expired right now we are never checking if the token has expired and remember it only lasts for an hour that means that if the user is logged in for more than an hour and he tries to make a certain change like create a post or delete a post or edit it he won't be able to do so in that case we have to check it and we have to log him out so right now i'm going to open the console and the application tab we can clearly see that our user is logged in right now and if we refresh he's still going to be logged in i'm not sure if an hour had passed but let me try to delete this as you saw i just tried to delete a post but nothing happened and if we go to the console well we don't get a lot of information but if we go to our network tab and take a look at a request you can see it is still pending and we don't really have a lot of information on what's going on but if we go to the back end that could give us more info so right now i'm going to open the server and take a look expired that means that we are not allowed to like or delete a post there is going to be a simple way to solve this and that is if token is expired we simply need to log the user out for that we're going to head to our nav bar what we have to do is we have to check if the token is expired how can we do that well we first have to check even if the token exists and then if that's the case we want to decode it we can decode a token like this kant's decoded token is equal to the code and then we pass in the token that the code is the function that we need to import we need to import it from jwt the code so import the code from jwt the code that way it's going to give us information on when this token is expiring finally we need a simple if check that is going to be if decoded token exp that's the expiry multiplied by a thousand is lower than new date and then finally dot get time so we want to get the current time if that is the case we want to log out so if the decoded token that expiry multiplied by thousand this is going to be a certain value in milliseconds if that is lower than newdate.gettime so this is the current time in milliseconds in that case we simply want to call the logout action and that is in this case this function here which is going to dispatch the logout and then push us back if we save that that should be it now considering our john wick was expired or his token was as soon as we came back to the page we were signed out on the signed out users as you can see we have nothing we cannot even like them and we also don't have a delete or edit button now if we go ahead and try to sign in as a different user for example javascript mastery there we go we can like it but we cannot delete or edit and let me try to create one new post let's do something like mern 3 is now out you guys have been requesting this video for so long and now it's out i'm gonna say awesome tutorial and tags is gonna be auth and all auth something like that there we go so let's choose an image we can also choose fireworks and submit it there we go as you can see we can edit it we can delete it we can like it yeah you can like your own post nobody's saying you should do that but you can and finally if we log out now and sign in with a different person like john wick there we go we have this different pose that can be only liked but cannot be deleted or edited a smart place to start would be to create the pagination component so we can go to client we can go to the source and components and then right inside of here we're going to create a new file called pagination.jsx inside of here we're going to import react from react as we always do we are also going to import some of the components from material ui lab we can say import and that's going to be pagination as well as the pagination item and this is not being imported from material ui core because these are still experimental features so we're importing them from the material ui lab library of course we're going to have some styles so you can say import styles from dot slash styles and of course you could have done this in a folder but in this case i'm just gonna do them right in here and that's going to be styles.js the styles for the pagination component are going to be incredibly simple we can say import make styles from add material ui forward slash core forward slash styles this is how we usually do styles in material ui finally you can say export default make styles and then in there we call that as a function and provided a callback function that instantly returns an object like this it is a bit of a weird syntax but we have to do what we have to do inside of there we'll have only one class called ul and then it's going to have the property of justify content is equal to space round great that's going to be it for the styles now we can go back to the pagination component and continue working on the jsx our pagination is going to be a react component called paginate and it's going to be of course a functional component inside of there we're going to use our classes by saying cons classes is equal to use styles and then we call that as a function and at the top this should have been used styles and not styles great so now we have the classes now what are we going to return well the return is going to be the pagination component that we are importing right at the top that pagination is going to be a self-closing tag but it's going to have a few props the first prop is going to be classes and classes is equal to object and then inside of there ul is equal to classes dot ul moving further we're gonna have a count this is the number of pages in this case we can make count equal to five this is just a static amount but we'll have to dynamically fetch the number of pages depending on the number of posts we currently have then we have to have the current page in this case let's only say something like one of course this is later on going to be dynamic as well then we're going to have a variant which is going to be simply a string of outlined we're also going to have a color which is going to be equal to primary and we're going to have a render item property which is going to be a dynamic block of code with a callback function inside of there our callback function is going to take an item as a prop and we're going to instantly return something so we're not going to use curly braces we're going to use immediately simple parentheses the thing we're going to return is going to be a pagination item which is yet again a self-closing tag inside of there we're first going to spread the item so we want to pass all of the data from the item right inside of the pagination item then we're going to say that this pagination item is going to be a special link component that we're importing from react router dom so we can say import link from react router dom great we're going to use this for routing and then finally we have to see where is this pointing to so we can say 2 and that 2 is going to be equal to a dynamic string of course and then inside of there we can say something like forward slash posts and then question mark page is equal to and then a dynamic page which is in this case going to be 1 but later on we're going to have a real dynamic link now if we save that of course we have to do export default paginate and with that said our currently static pagination component is now done so we can import it somewhere and start using it we are going to import it inside of our home component inside of there we are going to import pagination from dot slash vagination in this case we don't have to do pagination forward slash pagination because it's not in a special folder great now that we have it let's see where we can actually call it i'm going to scroll a bit down and then in here just below our form we want to call our pagination but we're going to call it inside of a paper component that paper is going to be coming from material ui so just at the top we can import that paper paper is just a white div that paper is going to have a class name that is going to be equal to classes dot imagination it's also going to have the elevation equal to 6 which is going to give it a nice shadow finally inside of there we can call our pagination component of course it is a self-closing tag as you can see currently we don't have classes in there so i'm going to delete that and we're going to do that later because we have to do a refactor of the entire home component now if i save this and go back as you can see just below this form doesn't look that pretty but we have our pagination component with five pages as we specified currently if we click that nothing is going to happen because we are navigating to forward slash posts question mark page is equal to one but our current client side navigation doesn't know what that is because all the posts are simply on localhost 3000 so we have to make our client side navigation and react router work with the current new pagination system first of all we're going to import one more thing here from react router dom and that is going to be a redirect component then we can start working on the jsx i'm going to change this from lg large to xl which is extra large because we want to fit more posts on the screen then we have our navbar and then we have our switch so first of all we're going to have a path just slash which usually renders first on the page we don't want to render a home component there what we want to do is call a callback function which is simply going to call the redirect component and that redirect is going to redirect us to and that's going to be forward slash posts so we only want to see posts if we are on this specific path and we're going to be immediately redirected if we do this of course we have to keep in mind that if we want to show something on this specific route we also need to create it so just below the current route i'm going to create a one more self-closing tag this one is going to have the path of forward slash posts it's also going to have the exact parameter and it's going to render the component called whole before we were rendering the home component on the just slash path we can now copy and paste this home route just below because we also want to render the home component if we are on the forward slash posts forward slash search this is going to be rendered when we are searching for something and then in here we'll be able to provide some more parameters like search query and so on but for now it's important for us to have this right here then below that we're going to have one more route that route is also a self-closing component that has the path which is equal to forward slash posts and then finally forward slash column id this is going to be the post details path and this column id means that this id is going to be dynamic finally we're going to render a component called post details of course we haven't yet created or imported postdetails component so let's do that right now inside of our components i'll create a new folder called post details inside of there we can create a new file called post details dot jsx and inside of there we can create a new react component we can use the raf ce this is the extension for es7 react redux snippets so i'm going to use that which is simply going to generate a react component for us but of course you can write this by hand if you want to for now in there we can simply put a konza log that's going to say something like post details and we can also just render a string of post details in the jsx just so we can see if our component is showing up now let's go back to the app and then in here let's import that pose details component by saying import post details from post details i just want to point your attention to this nice tool i've recently started using which is called tab 9. you can see it's using ai to autofill code and it immediately knew that i wanted to autofill this exact thing which is kinda crazy if you think about it but with that said we are now creating and importing post details and we are pointing to it when somebody goes to post and then a specific id let's see how that looks in action if we try to remove the forward slash posts and just check the localhost 3000 and click enter that's going to point us straight back to forward slash posts exactly how we want it then we also added the forward slash search that works we are right there and then we also added a specific post page post details and in there you have to enter some id right now it doesn't matter which id we enter so let's try with one two three and as you can see if i zoom it in we have our post details right in here finally we have our forward slash odd page which is going to be our sign in form if you open that up an alert is going to pop up and the reason why is because we haven't connected a real google sign in to see how you can set up full google authentication make sure to watch the third part of this series because there i teach you how to do exactly that for now to get rid of that alert we're going to go back to our auth which is in components and then auth right there we're going to scroll down a bit and we can see this alert we're simply going to swap that into a console.log for now that way the alert is not going to pop up if you don't have the valid google console connected but then again if you want to connect it you just have to watch the third part of the video and you're gonna have a valid id to connect it with with that said this is our odd route if i enter my email and sign in you can see that everything works right but somebody can still go to forward slash auth and see this page that shouldn't be the case if we're currently logged in we should only be able to see this if we're logged out so let's fix that we can easily fix that by going to app.js and then inside of here instead of rendering the auth we first want to check if the user is logged in and we can do that because we are storing our users information in local storage so i'm going to switch this from a parenthesis to a code block and i'm going to put all of this part inside of the return of this component so just here we're going to have a return and we're going to put all of the code here but before we do that we're going to have a const user which is equal to json.parse and we want to parse the local storage dot get item and we want to get the profile that way we'll have the access to the user variable now depending of the state of the user we can render something different here instead of the odd so we can have a callback function and then there we can say if no user then we want to render the auth component that makes sense right we want to render the odd if the user isn't logged in but if they are we simply want to redirect the user so redirect that is a self-closing component that's going to point to forward slash posts just like this let's see if i have that correctly that looks fine to me so now if you go back and if i try going to forward slash auth it's simply going to redirect me back to posts great that was our refactor of the app.js component now we can start the refactor of the home component so that we can accommodate it to use the pagination let's navigate to the home component and let's see what changes do we have to make there are gonna be quite a few because a home component is going to be a really important component that's going to handle the logic for the pagination and some other stuff so let's make our life easier by first importing all the things we're going to use we're going to import a few things from material ui and those are going to be the app bar the text field we're gonna also use a button and finally a paper which we already have right there then we're going to import some things from react router dom these things are going to be called use history and also use location we're going to use that so that we know on which page are we currently and we're going to use the history so that we can re-navigate to certain pages and search terms that's going to be imported from and that is going to be react router dom inside of here we're going to also use something known as a chip input and we're going to import the chip input from and that is going to be material ui chip input chip input is a normal input but it works great for tags let me show you what i mean right here on the top right i can search for tags let's do europe and you can see this is not a general input this is a chip input so it turns it into this spill-like structure we can also search for asia we can search for usa and all of these are going to be in so called chips so that is what we'll be using for our tags we also have to set up our url search params we're going to use that to know on which page are we currently on and what search term are we looking for to do that react router dom says to use a function and call it use query that use query is just a normal function and in there we are returning new url search params we call it and pass use location which we call again and call the dot search after that that simply allows us to use it as a hook so we can simply say cons query is equal to use query as you're used to we also have the use history so we can say const history is equal to use history query is where we'll be getting our page info from so you can say something like const page is equal to query dot get and then in here we can say page so this is going to read our url and see if we have a page parameter in there if so it's going to populate this variable so we can say that or one so if you don't have the page we must be on the first one finally we're also going to have a search query so we can say cons search query is going to be equal to query.get and that's going to be search query great now we have some of the things that are necessary and now let's modify our jsx the first thing that we're going to modify is that we're going to have our container and that container is going to have a max width equal to xl then we have this grid container and the only thing we're going to do with it is we're going to give it a class name the class name is going to be equal to classes dot grid container for now we don't have classes but don't worry we're going to import them really soon then we're going to have our grid item and in this case we're going to make it a bit more mobile responsive by saying take 12 spaces on mobile then take half the screen on a bit larger devices and finally on medium devices so take three quarters of the screen on bigger screens we want our posts to take most of the screen finally on this screen where we have our options like the form and the pagination we can leave this as 12 then on small devices that's gonna take the half the screen and on medium devices it's the screen is big enough so three spaces are going to be just enough finally we're going to make this look a bit better because now we have the form we have the paper pagination and soon enough we're going to have the search as well so let's add something known as the app bar app bar is going to have a class name equal to classes.app bar search it's also going to have the position which is going to be equal to static and it's going to have the caller which is going to be equal to inherit inside of that app bar we're gonna have our search so inside of there we can create a text field that's going to serve as our search the text field is going to be a self-closing component and it's going to have quite a few properties the first one is going to be the name which is going to be equal to search then it's going to have a variant which is going to be equal to outlined then it's also going to have a label our label is simply going to be something like search memories we have many props for text fields so i'm going to put them all in separate line then we're also going to have a full width prop we're also going to have the value which is going to be equal to a search for now we can say something like test then we're also going to have the onchange property which is going to change our value so for now i'm going to leave it as an empty function like this and that's going to be it so now let's add our classes and we'll be able to see how this looks like in action as you know the procedure for adding classes is similar so we can simply say import use styles from dot slash styles that's it and finally we need to create the styles.js file inside of the home folder as always to save your time i'm going to simply give you the code give it the styles to simply copy and paste them it's nothing special adding some border radiuses some display flexes padding margin and so on nothing scary you should worry about but just to save some times you'll be able to find all the styles i mentioned in this video down in the description so just go ahead find the link and paste them right in here once you're done with that we need to call our use styles as a hook so we can say cons classes is equal to use styles and we call it like a function now if we save this we shouldn't have any errors and we can check it out in the browser and that already looks so much better take a look now on big screens our posts are taking more of the width and we have our search on the right side which already looks good of course we cannot currently type in it because we have a constant value in react we have to manage the fields using state so let's create a state field for our search memories field we can scroll just a bit up and then in here we can say const search and set search is going to be equal to use state and then inside of that state the default value is going to be an empty string now let's use that state variable and put it right here instead of this static test value and let's do something on change so what do we have to do on change well we get the event and then inside of there we can say set search is equal to e dot target that value that's going to allow us to change the value of the search one thing that i often prefer is not having the need for a button so we also want to make something happen if we click the enter key so let me show you how we can do that we can add just one more thing onto this text field which is going to be called on key press and then on key press we're going to create a function called handle key press that function is going to be just right here below this use effect const handle key press it's going to accept an event that's going to be a key press event and we can simply say if e dot key code is equal to 13 in that case we want to do something we'll want to search for the post for now we don't have to logic to search for the post but i'm going to add the comment search post right here so we can add it later on key code 13 simply means the enter key so to know if the key code is 13 you press enter great now before we add the search post functionality i also want to add the jsx for the search by tags to do that we're going to use the chip input we imported at the top our chip input is also going to be a self-closing tag and it's going to accept a few properties first it's going to accept some styles you can have an object in there and say margin is equal to and then a string of 10 pixels top and bottom and 0 pixels left and right we also need a value for our search and this value also needs to be dynamic it has to be from state so let's scroll to the top and let's create a tags state field i'm going to simply copy this line replace this for tags and set tags and at the start it's not going to be an empty string it's rather going to be an empty array because we want to have multiple tags now scrolling down we can add the value of tax we're also going to have the on add function and the on the lead function for now we're going to leave this as empty and we're going to populate them soon we also need to have the label which is going to be equal to search tags and we also need to have a variant which is going to be equal to outlined just so it matches the text field on add we're going to call the function called handle add and then on delete we're going to call a function called handle delete and of course we have to create those functions so scrolling a bit up right in here we're going to create that function const handle add and it's going to accept a tag as a parameter finally what we have to do is we have to call the set tags state and then inside of there we're going to have an array as the state when you have an array with states you first have to spread the previous tags and then add the new tag onto it this is how we're going to handle the add tag and finally let's also handle the delete so we can say handle delete that is also going to accept a tag but more specifically tag to delete and what we have to do is we also have to set tags but inside of there we're going to say tags dot filter where we get one specific tag we can put it like this tag and we want to filter out the tag to delete so we can say if tag is not equal to tag to delete we're going to keep all the other ones but we're only going to delete the tag we want to delete now let's add that there we have a handle delete and a handle add function let's save it and see how does it look like as you can see we have search memories and we have search tags let's try adding test a tag appears let's try test one test one appears and we can finally test it by deleting them which also works final thing of course is to add a button that's going to do something with those inputs a button is not going to be a self-closing tag it's going to have the on click property and on click we want to do something and that something is search post search post is a function we haven't created yet so then we can create a class name which is going to be equal to classes dot search button and we can also have a caller which is equal to primary finally inside of the button we're going to say search now if we save this and take a look it's not going to work because this is undefined so we have to create that search post function we can create a search post right here below the use effect so const search post is equal to a function which doesn't accept any parameters inside of there we want to see if we have a search term so we can say if search this search maybe is not the best name a better name would be something like search term or title or something like that but in this case it's search and we also want to trim it to make sure there are no empty spaces so if we have a search term then finally we want to dispatch some logic to fetch our searched post so fetch search post great of course to dispatch this we're going to have to use redux and we're going to have to modify our database to only search for specific posts and else if we don't have a search term then we're going to simply use the history object and call the push method to forward slash we just want to redirect back because we have searched for nothing and as you can see here we have this comment we also want to call for the search post function right inside of here if we press the enter key now that we have this let's take a look in the browser we have our two inputs but the search button doesn't look right looks like we're missing something the thing are missing is going to be the variant equal to contained let's save it and take a look search memories search tags and they search button but of course if we search something right now nothing is going to happen but now comes the hard part we have to tell the database to only return us the posts that match our query to send a nice message to the database we can use redux so let's first create a redux action and a reducer to manage our posts this patch is the verb that we use with actions so to have something to dispatch we need to create an action for searching the posts to do that we can open up our file explorer go to actions posts and then inside of there just below our previous get posts we want to create an action called get post by search so we can say export const get posts by search that is going to be a function and it's going to have the syntax as you can see as all the previous actions do we're using redux tank for asynchronous actions and again tab 9 does a wonderful job of just immediately filling this out for me again the link is going to be down in the description so you can check out tab 9 maybe install it as a visual studio code extension and let's see how do we want to fetch the data well as before we're going to have a try and catch block so let's create it try and catch and then in the try we want to do something like const where we get the data inside of the try block we want to try to communicate to our back end so we can say cons we destructure the data and that is going to be equal to await api dot fetch posts by search which is a function of course our get post by search is going to accept a search query as a parameter and we're going to pass that same search query to our api request for now we're simply going to console log the data and we're also going to console log the error if there ever is one now we have to go to our file explorer api and then index.js because we have to create the api endpoint called fetch posts by search so let's go right there and then just below fetch posts we can create our fetch posts by search it's going to be really similar so we can say export const fetch posts by search this time it's going to be a function but it's going to accept a parameter of search query finally we'll be making an api dot get request to forward slash posts but we have to provide some information about our search the endpoint is going to be for slash posts for slash search but now inside of there we're going to use query parameters query parameters start with a question mark and then you specify a variable name search query and that search query has to be equal to something so for example you can pass a static value of test but we're going to make a dynamic so i'm going to make this into a dynamic template string and then we're going to use the dollar sign curly braces syntax to make this equal to b search query dot and then we're going to use the search and if there is no search then we can say or simply do a string of none but we also want to add something else so after that we can say end and now we want to handle our tags it's going to be the similar situation tags are equal to and then inside of there we can say search query dot tags now we're sending all of the information to our search endpoint great now we have our endpoint and we also have our action so we can go back to where we were to home and then from here we can dispatch that action we can first import it right here it's called get posts by search and finally we can use it right here in the same way we used get posts that is going to be equal to this patch we pass the get post by search and we call it as a function but remember this action is going to take in some parameters more specifically it is going to take the search query object as we specified inside of that search query we have to provide our search which is coming from state as you can see here but we also have to provide tags which we have to render into a string because we cannot pass an array through the url parameters because of that we're gonna do tags is equal to tags that join and we're going to join them by a comma that way if we have an array of something like let's say that we have tags of europe and let's say usa that is going to be equal to a string of europe and then comma usa if that way we'll be able to more easily pass the data from the front end to the back end now we have the action we are dispatching that action we're making an api request let's just remember to which endpoint to forward slash posts forward slash search with some parameters so let's create that endpoint on the back-end side we can go to our server folder and inside of our server we are going to go into routes we first have to create that post route we can create it just above our get posts and remember it is going to be to forward slash search before we said it's going to be forward slash posts forward slash search but remember since we are in the post.js file all of these routes begin with post even though you cannot see it right here okay and on the search route we want to call a specific controller so just at the top we can import it get posts by search and we're going to call it once we get to that route and finally we have to create ad controller where most of the logic will happen so let's go to the controllers posts and then just below the get posts we currently have we're going to create a new controller export const get posts by search that is going to be an async function of course we have the rec and the rest in there and we also have a try and catch block now we want to retrieve that data from the rec.query remember that i mentioned params but params and query are actually two different things let me explain what i mean when we have a query that usually means that the route goes like this forward slash posts question mark page is equal to one in this case we would have a query where page variable is equal to one but if we have something known as params in that case our route would look like this forward slash posts and then forward slash colon iv in in here you would be able to put your specific id let's say one two three and in that case the populated variable id would be equal to one two three both ways are fully okay usually we use query if you want to well query some data like search and we use params if you want to get some specific resource like posts and then forward slash id of the post i hope that makes sense and that i explained it in a nice and easy to understand way if you like the way i explain things make sure to leave a like and let me know in the comments i really appreciate that and if you really want to be generous there is a buy me a coffee link in the description and that really allows me to keep creating more great videos for you guys with that said let's keep creating the logic for the search right at the top we're going to get the data from the query we just talked about const we get the search query and we also get the tags because these are the two things that we passed and we get them from reg.query now let's convert our title into a regular expression by saying cons title is equal to new reg x and then in there we're going to pass our search query and a flag of i i stands for ignore case that means that if you search for something like test or test or test it's all going to be the same it's not going to matter and we want to do that we want to get all the posts that match our search term we converted it into a regular expression in the first place because that way it's easier for mongodb and mongoose to search the database so let's search the database for posts by saying const posts is equal to a weight postmessage dot find now in here we have to write that query which is a bit more complicated but don't worry inside of here we can open a block of code where we're going to have the dollar sign or that or stands for either find me the title or find me the tags we want to find the posts that match either or so we can make that into an array and then the first thing in there is going to be the title so we're matching for the title the second thing in that array is going to be the tags we want to match the tags but keep in mind there is an array of tags so inside of there we're going to open another object i know it's getting a bit complicated and we're going to say in is there a tag in this specific array of tags that matches our query in there we can say in tags.split and now we have to split them by a comma because remember before we joined it just so we can send it over in a nice string i know it's a bit complicated but let me try to explain it one more time in plain english find me all the posts that match one of those two criteria the first one is the title is the title the same as we typed it on the front end and the second one is is one of the tags in the array of tags equal to our tags if that's the case then we want to display those posts finally once we have the posts we have to say res.json and then in there we'll have an object where data is going to be equal to posts and we're sending that back to the front end finally if we have an error we can simply return it to the front end by saying press that status that's going to be a 404 dot json and there we're going to have an object that has a message equal to error dot message so now let's go back to our action creator and check if we're receiving the data that's going to be right back to our actions in here and we'll have to destructure the data two times first time because we're making an axios request and the second time because we put it in a new object where it has the data property just like this finally we're console logging the data right here so let's go back to the browser and see if all the logic that we wrote right now actually works usually it is a miracle when everything works first time but who knows let's give it a shot so i opened up a console i am on my localhost three thousand four slash posts and i wanna search for the word the because we have it a few times in the coliseum we also have the acropolis so let's see if it finds it i'm going to click search and take a look at that we got back an array with four different objects representing four different posts the first one has the message of the most famous as you can see it right there the colosseum then we have the acropolis taj mahal also has the word the and finally the most famous paris museum also has the word the so that means that it works now let's see if our tags work i'm going to remove this and then in there i'm going to type something like europe if i search now we should get one more response but unfortunately i don't see anything so let's go back to our search form and see why is our search button not working for tags this is going to be a good debugging session opponent responsible for our search is going to be our home and right in here we can see that we indeed are dispatching the get post by search but it's a simple logical error i'm simply saying if there is a search term then this patch but we have to make it if there is a search term or if there are tags if we just add that that should fix the problem search for something like usa and click search we get three posts back this is going to be the statue of liberty in new york then we have the grand canyon and finally we have niagara falls which is bordering the usa and canada if that means that our tag completely works we're seeing the data in the console but now let's make it display that data and change the url on the client side doing that won't be that hard because we already set up most the logic to finalize it you can go to the components and then to our home component inside of here after the dispatch get posed by search we only want to do one more thing and that is to use the history dot push method to push our website to a specific url more specifically we want to go to forward slash posts for slash search question mark remember question mark is for the search query parameters we can say search query is going to be equal to search right the search is something that's coming from the state or none we can use a string of none if there is no search and then finally we're going to use the and symbol to set the tags tags are going to be equal to tags dot join and we're going to join the tags by using a comma remember we had to split them and then join them to use them again great this seems okay to me so let's see if we are being pushed to that specific url if i go in here and use the as an example as well as the europe as a tag let's see what are we going to be pointed to as you can see our url changed search query is now equal to the and tags is equal to europe we're going to use that to form our posts but why does this url on the client side even matter we formed it for the backend okay but why do we need on the front end well let's say that you search for some memories and you want to send to your friend only the specific search term with the terms and the tags already put there that way you can simply copy this paste it over and he's going to get the relevant information that's why we need client-side routing okay so now let's display those posts to display the posts we're going to go back to actions and we have them right in here so we have to do a similar thing to what we are doing right here in get posts i'm going to copy this and we're going to do it in the same way but we're going to rename our dispatch action type so let's create a new one by going to constants action types i'm going to copy this line and we're going to change it just a bit to something like fetch by search great so now we have one more constant we're going to go back in here i'm going to import it fetch by search and we're going to use it right inside of here and again we're sending the data to our reducers so let's go to our reducers posts and then right inside of here we're going to add one more case that case is going to be fetch by search and we can also import it right at the top now that we have that case of course we want to return something if that happens so we're going to return a similar thing in this case it's just going to be action dot payload now let's see what we're missing if i add that there that should be working let's go check it out we're back to just forward slash posts but i'm gonna search for something like asia i'm going to click search and as you can see now we got all the posts that have something to do with asia asia right there there there and everywhere that is great that means that our search works we can also try it by the title if i click search it's going to take a bit and as you can see we have all the posts that have the in the title that means that our search works perfectly now that we have that done before moving on to pagination and loading states let's do something easier like changing the background and the logo at the top and then inside of there i'm gonna remove both of these background colors and we're simply going to say background color is going to be equal to hash symbol and then f7 f8 fc this is a whitish color almost pure white now if we save that and go back you can see it looks a bit more professional maybe a bit plain right now both the background and the card are pretty much white so to make some separation let's add some elevation to the card we can do that by going to posts post and then finally pose.js finding our card component and then inside of there we're going to say raised and also set the elevation to be equal to 6. that's going to add this nice shadow that you can see at the bottom of the card which separates it from the background i can also see that we still have only two cards per row so let's make it like it was at the start of the video to do that we're going to go to post js this time and then inside of here we're gonna say show one which is twelve spaces on extra small devices still show one on small devices on medium devices show two per row but on large devices show four per that's three times four is equal to 12 and that is 4 per row let's see how does it look like this is already so much better in my opinion everything fits on one screen as you can see we currently have no pagination so we have quite a long list of posts now that we've changed the color the things that jumps out a bit too much is the memories logo at the top so let's change that as well to change it we're going to go to the nav bar and right in here instead of this memories png we have to add two new ones i'm simply going to open the images folder and then i'm going to paste it the links to download both of these are going to be in the description so that you can download them as well but once you actually do that we can go back to our nav bar and inside of there we're gonna have memories logo imported from memories logo and we're also going to have memories text imported from memories text now we can use those two images to make it look a bit more professional we can do that right in here we are no longer going to use this typography so we can delete it we are going to use two different images the first one is going to be the image self closing tag right inside of there the src of that image is going to be memories text like that and it's also going to have the alt tag of icon it's going to have the alt tag of icon and it's going to have the height equal to 45 pixels the one on the bottom is going to have the class name of classes.image it's going to have the source of memory's logo and the height is going to be equal to 40 pixels finally once we have that we want to transform this div into a link so i'm going to say link there more specifically link 2 and then we want to point to just slash now let's save that and see how does it look like in the browser there we go this custom logo just gives this project a bit more character i can see that the second image is a bit higher up than the first one so we can go to the styles and i'm gonna leave this style as well you can simply override it it's going to be down in the description i've made only a few small changes since the last video but then again make sure to copy and paste it just we're on the same page if you go back to the browser you'll notice that now they are aligned now that they've made the application look a bit better and now that the search is fully functional we can focus on pagination and loading states currently if i go back to the home there won't be any loading it's going to happen instantly but take a look we only have three posts and now they pop up so something doesn't seem right it's always good to have proper loading states so your user knows that something is happening so pagination and loading states coming up we already worked a bit with getting the page and the search query from the query parameters but now let's put that page to use we will no longer fetch the post from here from the home we're going to remove this use effect and we're going to pass our page straight to our pagination as a prop so in here we're gonna say page is equal to page that way we can go to our pagination and we can get it straight from props now inside of here we can create a new use effect so i'm going to say import use effect from react and we're going to declare it right in here our use effect as always it is a function with a callback function and has a dependency array so what do we want to do inside of that use effect well we want to fetch the posts any time that the page changes to fetch the posts as always we're going to use our dispatch with redux so we need to import a few things from react redux we can say import and that is going to be use dispatch so we can dispatch things and also use selector so that we can select some things from our state and this is going to be imported from react dash redux we also want to import an action called get posts so we're going to say import get posts and that's going to be coming from dot slash actions forward slash posts of course to get our dispatch function we can say const this patch is equal to use dispatch and then call it as a function now instead of this use effect we can say run it every time that the page changes so every time that the page changes if there is a page in that case we want to dispatch a specific action in this case we want to dispatch the get post action and let's open up that action side by side here just so you can see how it looks like get post you can see it accepts no parameters and in its current form it fetches all of the posts but that's not how we want it to behave we want to pass a page to it so that it only fetches the posts for that specific page and that's exactly what we're going to do right inside of there we're going to pass that page in now inside of our actions we can accept that page as a parameter once we have it as a parameter we can then pass it over to our api as well so inside of here we can pass that page of course now we have to go to that api and make some use of it so let's open it up in full screen as you can see fetch posts but now that function accepts a page and we can use that page to then filter it out so we can say api.get forward slash posts and then it's going to be question mark page is equal to dollar sign curly braces page that we're getting from the parameters of course we have to turn this into a template string and that's it now we're passing the data to the backend just so we know on which page are we currently on now let's go to the back end and modify our controller so that it returns only the data for that specific page that's going to be inside of the server and then finally inside of the posts controllers inside of here we have our get posts but that's basically now get post by page we can do similar thing that we did with reg.query we're going to say const this structure the page and that's going to be coming from rec.query because we're passing it through the query from the front end now we're going to have some extra logic in here just before we call the dot find on post first we're going to declare a variable called limit the limit is going to be the number of posts per page i decided to make it eight but you can change it if you want to then we have to get a start index of a post on a specific page for example the start index of the first post on the third page would be 8 plus 8 plus 8 minus 1 because we start from 0 and that would be 23 so let's create that first we have to convert our page into a number using the number constructor even though the page is a number on the front end when we pass it through the reg.query it becomes a string so we have to convert it back and now we are simply going to deduct -1 from that and finally multiply all of that by the limit this way we're always going to get start index of the post on a specific page we can even write a comment right there get the starting index of every page great finally we also need one more variable which is const total that is going to be equal to await postmessage dot count documents we want to count up all the documents so that we always know how many documents do we have how many posts do we have why do we need to know that well depending on that we're going to have a specific number of pages and we always need to know what is the last page we can scroll to that's why we have the total variable now that we have the total finally is the time to fetch the post so i'm going to rename this from post messages to posts and let's see how we can do it well we can say await post message dot find then i want to get the posts from the newest to the oldest because of that we have to sort them by id so i'm going to say dot sort we're going to pass in an object and say underscore id is equal to -1 this is going to give us the newest post first then i also want to limit them so we're going to call the dot limit on that and we're going to pass in the limit variable this is going to make sure to only give us for example 8 or 10 or or however many you choose per page and then finally we need to skip all the previous pages for example if you're on the page 2 you don't want to fetch first 16 posts again you want to skip the first 8 and because of that we're going to use the dot skip and we're going to skip all the way to the start index now we understand why did we have to create all these variables it all makes sense hopefully finally for all of this to make sense to the front end we have to pass a bit more data than simply posts so i'm going to pass a new object and inside of that object we're going to say data and the data is going to be equal to posts we also have to pass the current page which is going to be equal to number of the page so we just make it into a number and we pass that page and finally we also want to have the total number of pages that is going to be equal to math.seal and in there we're going to divide the total by the limit great that is going to give us the total number of pages now we're passing all of that data back to the front end and we have to make use of it of course where better to do that than in the action that we declared so i'm going to go back to our posts action before we were getting just the data for the posts and we're immediately passing it here but now that data is going to contain more info so let's see what is contained in that data object if i open up the console the current page is 1. the total number of pages is 3 and this should have been pages plural so i'm going to go back and just change that to pages what we had before was simply a variable that contained all the posts that means that we have to change the way our reducers view and render things the only thing you have to keep in mind here is that our payload is no longer just posts it's an object that contains three different things as we saw previously it contains the data of posts it contains the current page and also the number of pages let's go to our reducers which is going to be in here reducers and posts instead of simply returning the action.payload we have to return an object so right there i'll say return put that into an object and then i want to spread the current state these posts here are going to be more than simply an array of posts so i'm going to rename this to state you'll see soon enough why first we want to always spread the state when we're working with objects then we want to get our posts and now posts are not simply action.payload posts are equal to action.payload.data then we also have a current page our current page is going to be equal to action dot payload dot current page and finally we have number of pages which is going to be equal to number of pages again tab 9 really autofilled that easily great so now we're turning something different from the fetch all reducer it would be great if we immediately also accommodated the fetch by search in the same fashion so in the fetch by search we also have to make it an object inside of that object we're going to spread the state and then we're going to say posts are equal to action dot payload dot data you can also see that we are mentioning the posts a few more times here i'm just going to replace all of these with state considering that i renamed it at the top right here in our fetch by search this is not going to be action payload data it's going to be simply action payload that's where we have our posts considering that we've changed the structure of our state we have to find where are we actually using that state so that we can change it there as well let's search for use selector that points to us using the state we can see that it's being used in pagination but we're never actually doing anything with it then it's also being used right in here in the form and finally this is the one we're looking for use selector in the posts here is where we are using the posts before we simply had an array of posts but now we have an object where we have a property of posts inside of there so we have to destructure the posts right in here and the main reason we change this from an array to an object with multiple things is because we are gonna have multiple things we're gonna have the is loading property we're gonna have the number of pages and so on but for now we simply need to destructure this we can also add a question mark here to make sure to not throw an error if we don't have any posts available now let's save that and let's see if this is going to work we are back on our memories project and would you look at that we can see all of our posts that's great let's see if we can also see the posts that we search for for example let's search for europe again and it works we waited a bit but it finally gave me the posts that's great but that's something that worked before right so why even check it well we checked it because we changed a lot of things and you want to make sure that when you change some big things you check if you've broken anything but now is the time to check the pagination it's not going to work yet because even though we implemented all the logic for it we have to do one more step and that is use that logic inside of the pagination component so let's go back to it and do it inside of the pagination component we can now use this use selector to get the number of pages to do that we can say const the structure number of pages and make that equal to use selector inside of there we have a callback function where we get the posts and we want to retrieve state dot posts that is the reducer that's going to have the access to the number of pages finally we want to use that number of pages variable right in here under count number of pages only that we also have the access to the current page right in here so we can simply say right there number and page and just to be sure if we don't have a page we want to render or 1 to be on the first page i also noticed that right now i specified right there you select that is going to be use selector also in here posts page one in there we want to navigate to item dot page with these small changes we've made our pagination component completely dynamic let's see if it works going back to the browser first thing that you can see is that we have only three pages and that is correct because we have less than 24 posts let's try to go to the second page as you can see the url changed and even though it seemed for a second that nothing is happening because we don't have the loading yet it worked we got the second batch of posts finally let's go to the third page and there we go we got five more posts that means that our pagination fully works so we can switch between the pages and we can render only eight at a time this is incredibly important imagine that your application is used by hundreds or even thousands of users and that each user creates tens or even hundreds of posts imagine if your application had to load all 10 000 posts at once it would take so much time but why even do it when you can only see 8 at once that is why we use the pagination to cut down on low time anyway great work pagination seems to be done at least from what i can see right now hopefully there aren't any bugs and now we can move to the loading states to start working on our loading states you can head to posts actions redux makes it quite easy to have one central source of truth so we always know are we loading or are we not that's why we're going to use redux to accomplish the loading states so right inside of here we're first going to create two more constants action types right in here i'm going to create the export const start loading that's going to be equal to a string of start loading and then finally we're going to have one more which is going to be called end loading we're going to use this action types so that our redux reducers know when to start and stop loading we can go back to our action posts and we're going to import them right here at the top start loading and end loading the only question we have to ask ourselves is when do we want to start loading well as soon as we call get posts just before we try fetching the posts right in there we can say this patch and the only thing we want to dispatch is an action that has a type of start loading that's going to be it and when do we want to end the loading well it definitely has to be after we fetched all the posts which is going to be right here dispatch type and loading of course we want to have the loading states in a few more places also when we try to get post by search and so on so we can copy this start loading and we can paste it in a few more places before we try to get post by search we want to have it there we also want to have it before we create a post on update we're not going to go anywhere we're just going to update it so we don't have to have it there for the like does the same thing and for the delete that's also the same thing these actions by themselves are not doing anything we have to go to our reducers and then there create the logic for our loading states instead of here we're gonna also import start loading and end loading or is it stop loading let me see how i called it it start loading and then we have the end loading i also forgot to put it here at the end of the fetch by search so i'm gonna import it and loading and now we have to add it here at the top so what happens if we want to start the loading also what happens if we want to end the loading we're gonna prepare those cases and let's see what data do we want to return well of course we want to return an object as we always do we want to spread the state that we currently have and we only want to change the state of one variable and that is is loading is going to be equal to true if we want to start the loading and then we can copy this and paste it below same thing but we're going to change the is loading state to be false that's all that you have to do to manage loading in redux you don't have to do it everywhere in your code in all of the components whenever you do something cover the logic with changing the state you only do it here and everything is being done right here inside of actions it might be a bit confusing at the start but as you get more into it you'll start seeing the purpose in that back in reducers considering we change the way we view data we also have to change this state the state is no longer just going to be an array of posts it's going to be an object that's going to have the is loading property and that is loading is initially going to be set to true and also we're going to have the posts array great now that we've changed this we also have to change how do we get the data back once we like create update or delete posts the only thing we have to do is we have to everywhere spread the state so right here i'm gonna try to select multiple lines by holding alt and clicking at the start of each line right there i'm gonna open up an object and first thing that we want to do everywhere is we want to spread the state as we always did finally once we spread the state we want to set the posts inside of that state to be equal to what we previously had right there and then finally make sure to add the closing bracket at the end here here here and here i know that it might be just a bit confusing but we are basically switching from using just posts as an array to having an object that now contains the is loading state as well as the post state so that's why we have to turn this into an object spread the entire state and then finally only return the posts and also notice how we're doing stay.map spreading the state state.map state.filter that's no longer going to be possible rather we have to do state and then dot post and then dot map or that filter or anything so just to fix this we're doing state dot posts that map we're spreading stay that post stay that post set map and state of post filter these are going to be all the changes that we have to do with redux it is sometimes confusing i completely understand that but it's going to help us in the long run by maintaining one state of truth that said we can now actually start using the is loading state we can start in the posts.js file so we can open up our components and go to postspost.js inside of here from the u selector we're also going to grab that state is loading and now based on that state we can show some data so we're going to replace this for if is loading in that case we want to show our circular progress which is that loading state and we also want to add one if statement and say if there are no posts that length meaning if there are no posts in the array and if we're not loading in that case we want to return something that says no post because if we don't have any posts and we are not currently loading that means we're not going to load them they don't exist great so let's save that and see it in action i'm gonna reload the page and take a look at that we have this nice loading state at the top left of course you can style it a bit more make it big and make it in the center of the whole post but it's fine enough we see it on the top right corner now take a look what happens when i paginate it simply tells the user hey i'm doing something wait a second and it's so nice to have that visual feedback it makes your app look so much more professional same thing happens if you search something like the here and also same thing happens if we go for tags like asia there we go we have nice loading and only then do we see our posts and as you can see it works with searching the titles searching the tags doing the pagination or simply getting all the posts that's why i like using redux when you want to have one source of truth of course you could have used context as well and if that's your preference feel free to refactor this application from redux to using context we can go to the home component and right in here you should see that this is the place where we are rendering our pagination and the paper wrapping it first things first i don't always want to display the pagination i only want to display it if we are viewing the content by pages but if you're doing the search i'm gonna assume that the user doesn't have a lot of posts to search from like 10 20 or 30. in that way we don't need to paginate so what we can do is we can wrap this into a dynamic block and say if we don't currently have a search query and if we don't have any tags so we can do tags.length in that case we want to show our pagination so one more time let me just put this in here if we don't have a search query and if we don't have tags in that case i want to render the pagination if we have the search or the tags in that case we don't want to render the pagination now that we have that we can also add the class name here and that's going to be classes dot pagination let's save that and see it in action there we go as soon as i save that you can see it looks just a bit better it is displayed right there let's try to sign in to see how does it look like with the form there we go looks extremely good there we go it looks extremely good i also see that we don't have this shadow on the form so let's add it as well right there i'm gonna search for creating a memory right in here search creating a memory and there i can see that that is in the form file so i can just add the elevation equal to 6 to this specific paper if i go back you can see that even the form now has the shadow and all the elements in the page have shadow to make them pop up from the background our pagination is working our search is working our design is good what else do we have to do well of course we have to implement the dynamic memory details page when you click on the memory we want to display everything about that memory in a nice view so let's do that right now to implement the memory details page we first have to see what's going to happen when we click on a specific post to figure that out we're going to go to posts and then post right in here that's not post details it's just the post component so we have to make something happen once we click on this card and the thing we're going to do is we're going to import one more thing from material ui which is going to be the button base and just below this card we're going to add a button base component we're gonna give it a class name which is equal to classes dot card action and it's also going to have the on click property on click what do we want to do well we want to open the post we don't have a lot of props so i'm going to put them in one line and finally the ending tag of this has to go below the card content so i'm going to copy it and put it just below the card content but still above the card actions great open post is not defined so let's define it const open post is going to be equal to to an arrow function for now so how is this open post gonna work well it's going to be incredibly simple the only thing we want to do is we want to navigate to a specific url so to do that we have to import use history from react router dom import use history and that's going to be from react router dom we already learned that we have to call it as a hook which is going to be const history is equal to use history and then finally inside of the open post we can simply say history dot push and then we're gonna push to forward slash posts forward slash and then post dot underscore id so you're pushing to the id of the post that is currently selected and everything else is going to be done for us in that post details page so we know that if we go to forward slash post forward slash id if we go to our app you can see posts id belongs to the post details page so everything else will have to be done in here and in redux actions this is going to be a fairly large component so let's start right away we first want to import react and we also want to import the use effect from react then we want to import a few things from material ui and those things are going to be paper typography we also want to have the circular progress for loading and finally the divider and this is going to be imported from add material ui for slash core then we also want to import a few things from react redux and that's going to be the use dispatch as well as the use selector to get the data about the post as i said these are coming from react dash redux then we want to import moment from moment moment is a js library that deals with time and finally we want to import a few things from react router dom those things are used params and also use history from react router dom great we also have some styles so we can say import use styles and that's going to be from that slash styles as you can see we don't yet have that file so let's create a new file styles.js and as always i'm going to provide you with all the styles you can simply copy and paste them right in here they're going to be down in the description while they're scrolling to the description make sure to leave a like and leave a comment for the youtube algorithm now that we have the hooks for dispatch selector params history use styles let's declare all of those hooks at the top first we're going to get the data about the post from use selector that's going to be const post posts and is loading and that's going to be coming from use selector in there we have a callback function with a state and finally we want to get the state dot posts reducer then we want to say cons dispatch is going to be equal to use dispatch we also want to get the history so we're going to say cons history is going to be equal to use history we also want to get the classes so cons classes is going to be equal to use styles and finally we also want to get that id so we're going to say cons the structure the id and that's coming from use params remember our url we're going to forward slash posts forward slash an id great we've prepared everything to start creating the jsx layout of our post details component considering that the post details component is incredibly similar to the post component it's gonna be a card or a paper that's gonna have some typography where we display all of the post details because of that i'm gonna give you the jsx code for some parts of our post details component i'm going to paste it in here you're going to find this in the description down below the only thing that's not in here is the most important one and that is the logic for the recommended posts we're going to code that together but before we do that we have to create the data for getting a single post if you remember correctly so far we've only worked with posts plural now we have to create the logic for fetching only a single post based on the id so let's start with that we first of course have to dispatch some actions we're going to do it inside of the use effect and that use effect is going to happen whenever the id of the post changes right inside of there we can dispatch an action and the action we're going to dispatch is going to be called get post action of course we want to get the post by some specific id so we can pass that id in there as you can see our get post id is not yet defined so let's import it we can say import get post and that is going to be coming from dot dot slash dot slash actions forward slash posts now is the time that we create this action and make an api to the backend that's going to serve us all the details about our specific post let's go to our posts and more specifically actions right inside of here we're going to create one more action creator and we can actually do that by copying the get posts i'm going to paste it at the top and there are a few changes we have to make first of all it's not going to be get posts it's going to be get post second thing is that we'll be getting an id as a parameter and that id is the thing who will pass into our api call then the actual api call is not going to be done to fetch posts rather it's going to be to fetch post and finally our type is not going to be fetch all it's simply going to be fetch post so let's go to our constants and then right inside of here we can create a fetch post action constant great going back now we can import it fetch post and now everything is ready besides the actual api endpoint so let's go to our api index.js and then inside of here we'll have to create the fetch post that's going to be export const fetch post as we discussed we're getting the id as a parameter and then we have to call the api dot get and we have to navigate to forward slash posts and then forward slash id now everything is ready and we have to go back to our back inside and bring us the data so let's go to our server more specifically routes and then posts inside of here we have to create a route for getting a single post we can do that right in here router dot get and the route is going to be to forward slash column id this means that it's going to be a dynamic id and what controller do we want to call well we want to call the get post controller of course we need to import it at the top get post and finally we have to create it under posts controllers if we scroll down you'll notice that we already have a good get post controller we created this in one of the previous parts and we never actually used it but now is a good time to do so let's see if everything seems right we're doing the const id from wreck params and we're trying to find that post by id and finally we have res that status 200 and we're sending that post back that seems all right to me with that said let's go back to our front-end side to our actions now we know that we are getting that post back right here as the data and we are sending it as the payload to our reducers so let's go to our reducers post we have to import that action type which is going to be fetch post our fetch post is going to be similar to fetch by search so we can copy it the only thing we have to change of course is the case it's going to be fetch post and then in here instead of setting the posts to be action.payload in this case we're getting a single post so we're going to set it right in here post is equal to action.payload i know that we've written a lot of code without actually seeing what's happening but we've been dealing with data mostly now we're going back to our post details and see now we have this post right in here if it says right there that we don't have get posts make sure to close the file and then reopen it and it's going to be all good looks like our posts are not currently rendering let's open up the console and it says that we have failed to get a connection there is a network error so let's go back to our code and open up the console as you can see here it says identifier getpost has already been declared and the error is in routes post js line three and indeed you might have noticed it but we are already importing the get post here and here so we don't have to do it twice i'm gonna save that and now we're gonna go back to post details component let's go back to the browser and see if it works okay our posts are loading right now and take a look at that if you hover over them you can click them so let's try by clicking one memory and see what happens okay there is an error it says cannot read property title of undefined this usually means that we were trying to render something before the data was actually fetched so if we go back into our post details we just have to add some checks well first of all we're going to say if there is no post then return null and then second of all we're going to add the loading state so if it is loading in that case we want to return a paper component that paper is going to have the elevation equal to 6 and it's also going to have a class name equal to classes dot loading paper and finally inside of that we want to have the circular progress component it's going to be quite a big one so i'm going to set the size to be equal to 7 em we're gonna save that and now these two checks are making sure that we don't try to render this jsx where we depend on the post if we don't have the post already if we now save this and go back to the browser you can see that our post opens up it has a nice title we're listing the tags right there description who created the post and when the post was created i also added some paragraphs here to let you know that real time chat and comments could be coming soon let me know which one you'd like to see first i would really like to create the fifth part of the series if there is a lot of demand for it from you guys with that said let's check out our loading states if we now go back you can see there is loading right there and if i click on one of these specific memories you can see this nice loading at the center but we can see it for less than half a second that's because i have a really quick internet connection but what would happen if somebody is running this with a slow internet connection well we can actually check that out and that's one more trick i want to show you you can open up your developer tools go to the network tab and then there you'll see the no throttling thing you want to switch that to fast3g now this is going to emulate a slower internet connection so let's go to memories and see how nice it is to have a visual representation that something is loading there we go our posts are there and let's try to load a specific memory this loading looked really good now let's bring this back to no throttling and let's close it and let's for a moment admire this nice memory details component and the prague hassle once we're done with that we can focus on the most important part of our memory details component and that is the recommended posts section let's code that out together right now let's code out the recommended posts part i'm going to close all the tabs besides the post details which we're going to have open right here and i'm going to collapse it and close the file explorer just so we have more space to work with the interesting thing about the recommended posts is that we're going to use the same endpoint we created before get posts by search so i'm going to create one more use effect here and yes you can have multiple user effects per functional component inside of there we're going to have a dependency array that's going to have the post so whenever the id changes the post changes and then we want to do something for each post we want to see if the post exists and if it does we want to dispatch a new action creator that action creator is not going to be get post anymore it is going to be get posts by search the one we created before so we can say right here dispatch get post by search and finally we have to provide that search query in there so we can say something like search is going to be equal to none because we're not looking for search we're looking only for tags that's what we're gonna use to recommend the posts so we can say tags is equal to post question mark dot tags dot join and we want to join it by a comma now if we save that this is going to populate the posts at the top finally we can use those posts to create a list of recommended posts const recommended posts is going to be equal to posts dot filter inside of there we want to get our specific post but more specifically we want to destructure the underscore id from there and then we want to keep all the posts but delete the one where the underscore id is equal to to the current post that underscore id of course the current post cannot be in its own recommended posts that's why we are doing this so in here we can say if we have recommended posts so if recommended posts that length if that is the case then we want to display something that something we want to display is going to be a div with a class name equal to classes dot section inside of that div we're gonna have a typography and that typography is going to have a gutter bottom to give it some margin at the bottom it's going to have the variant of h5 and then inside of there we can say you might also like finally below that we're going to have a divider and below that divider we're gonna have a div and that div is going to have a class name equal to classes dot recommended posts inside of that div we want to open a dynamic block and we want to map over the recommended posts by doing recommendedposts.map inside of that div we want to open a dynamic block and say recommendedposts.map so we want to get a post in there and we can immediately destructure all the things we need from the post like title we also need a message we need a name the number of likes and the selected file as well as the underscore id now with all of those things we want to return something so we just use a pair of parentheses and the thing we want to return is going to be another div now let's see how this is going to look like if we just try to render out the title i'm going to save it and let's go to a specific memory details and if we scroll down we can see you might also like this let's see if we have something different in here it only gives us the pose that we're currently on which is not a good thing we need to get all the other posts so i might have made a logical mistake in here we need to have a not equal to because we want to filter out only the one that is equal to and we want to keep all the other ones so now if we go back as you can see now we get all the posts that have something to do with europe that's good but let's make them into a nicely styled cards this div is going to have a style property inside of there we're going to have an object with a margin of 20 pixels and we're also going to give it a cursor which is equal to pointer that means that it's going to show a pointer once we hover over it finally we need to have an on click function what's going to happen once we click it and on click we simply want to open up the post so i'm going to put a callback function right here and we want to call the open post function and pass it the underscore id of the current post finally we also need to specify a key and the key is going to be underscore id of course we don't yet have this open post function but we're going to create it right now so let's go to the top and let's create it const open post is going to be equal to we're getting in the id and what do we want to do with that specific id well we simply want to push to it so we can use the history dot push and we want to push to forward slash post forward slash and then to that specific dynamic id i see the id is being used currently so i'm going to use the underscore id here as well now if we save that let's see if that's going to work we're currently on dubrovnik we can see that we added some margin and let's go to for example the coliseum that's great it gives you the feeling that you can browse through the page and see all the different things that are available great now let's style those cards a bit more and show some more details with each one of them instead of displaying simply the title we're going to display a typography component that typography is going to have gutter bottom it's also going to have variant equal to h6 and in there we're simply going to render our title now i'm going to copy this one four more times or rather three more times the first one is going to be h6 because it's the title and the second one is going to be of a variant subtitle 2 and it's going to render our name then we're going to have the message below and message is also going to be subtitle 2 and finally we're going to have the last one which is the likes and that's going to be subtitle 1 and we can just add in front of it likes is equal to and then we can say likes dot length and let's not forget about the most important part and that is the image so we can add a self closing image tag right here the image is going to have the source equal to selected file and it's also going to have the width equal to 200 pixels if i now save this let's take a look in the browser that looks so much better as you can see we can see all of the posts recommended right there that have something to do with europe but let's go back and let's see if we go to niagara falls if we can see some different recommended posts now we have the statue of liberty and grand canyon let's check out the statue of liberty looks great we can see all the info the image on the right and we have the idea that we can actually navigate through the page with recommended posts being done our whole memory details page is done as well with all of the changes that they've made there are also some things that are not working right now because of the way how we structure the data in our redux for example before as you know the posts were simply an array of posts but right now we're getting an object where then we have the array of posts so there are a few places where we have to fix that one of those places is going to be the form formjs component and then just at the top see here state dot post dot find in this case it's going to be state dot posts and one more time dot posts so you can find a specific post now let's go back to our app and let's see if all the functionality still works let's search for something like let's do sydney that works let's search for something like let's do usa that works as well let's see if the pagination works it works perfectly that is always great and let's try to sign in to see what else can we do i've just signed in let's see if we can like the post we can so that's good there we go we liked a few posts the liking functionality still works let's try creating a new memory let's go with test test test and i'm going to add a file the file is there and if we click submit it's just going to stand there we have to use history.push to navigate it to that newly created memory detail we can do that by going to form finding where we are actually creating that post and then just after that dispatch we want to use history dot push it's going to be pushed like this and looks like we are not importing it so just at the top we have to import use history from react router dom and you know the drill we have to say cons history is equal to use history and finally history dot push forward slash posts where are we going to get the id well we cannot get it in here we have to get it just after we created this specific post so what we can do is remove this and not call the history.push here rather pass one more parameter to the create post action reducer we're passing the history object we can go into our action creator accept that history object and then after the post is created what we can do is we can say history dot push and then in here we can use data dot underscore id that's going to re-navigate it for us let's save everything and let's create one more post test test test and i've added the image i'm going to click submit and there we go we are immediately re-navigated to a newly created post and if we go back you can see it right in here let's start implementing our comments section that's going to be inside of the client folder inside of the source components post details and then inside of here we're going to create one more component that component is going to be called comment section.jsx this is a new component that contains all the logic about comments so let's import react from react and we're also going to import a few hooks these are going to be use state and also use ref right below we're going to import everything we need from material ui and that's going to be typography we also need the text field and finally we need a button component that's coming from add material ui forward slash core also we're going to use the use dispatch hook belonging to redux so we can see that's coming from react dash redux and we're also going to use some styles so we can say import use styles and that's coming from dot slash styles great now we have the majority of imports that we have to do and let's create our component const comment section and that's going to be equal to a functional react component inside of there for now let's simply console.log something like comment section and also let's simply return an h1 just so we can see something on the page for now great of course we have to do export default comment section of course we have to use this comment section somewhere and that's going to be inside of the post details when we open more details about a specific memory so in here at the top let's import comment section from dot slash comment section just like this and where are we going to render that component well the last time we even left a typography saying where we need to put it comments coming soon so let's simply delete that and then instead of that typography we're going to render out our comment section it is going to be self-closing component and let's pass one prop to it and that prop is going to be the data for the specific post we're currently on we're going to use that inside of the comment section so let's go back to our comment section and let's immediately this structure our post data just so we know what's coming through there and maybe instead of this comment section let's simply console log the post great we already have enough code that we can see it on the website let's open up a specific memory page and then inside of here you can see that we have a big comment section now let's create the jsx for our comments inside of that div we're going to have yet another div and this div is going to have a class name equal to classes dot comments outer container right now our classes are not defined and to use the classes coming from the used styles we can simply say collins classes is equal to use styles and then we call it as a hook great now inside of this div we're going to have yet another div and this div is going to have a class name equal to classes dot comments inner container great now we have our layout now inside of our inner container we're going to have a typography component and that typography is going to have a prop of gutter bottom which is simply going to give it some bottom margin and it's going to be a variant equal to h6 now inside of there we can simply say something like comments now we have to loop through the comments of our specific post of course right now none of the memories or none of the posts have the actual comments because we haven't implemented the feature of adding them yet but let's create the jsx code that's going to loop over them once we have them populated let's open a dynamic jsx block and then in here we're going to loop over the comments for now let's create a use state field so const comments and set comments and that is going to be equal to use state for now in here we can leave simply an empty array because we have no comments yet now that we have comments let's loop over them comments dot map in here we're gonna get a comment i'm gonna put c for short and also we're gonna get the index then we want to instantly return something so don't put the curly braces here but simply a parenthesis now for each specific comment we're going to show a typography and that typography is going to have a key equal to i it's also going to have a gutter bottom and it's going to have a variant equal to subtitle 1. for now we can simply say something like comment in there or we can even make it dynamic and say comment i this is going to give it a number now just so we can see this let's add one two three four here that should render out four demo comments i'm gonna save that and in the browser we can already see our comments header and we can see comment zero one two three so we're already starting to create the layout for our comments later on of course we're going to have real comments in here but for now let's keep moving forward below the comments in our div we're going to have one more div and this div is not going to have classes it's simply going to have some inline styles we can say style is equal to width is equal to a string of 70 percent inside of there we're going to have one more typography we can even copy this one everything is going to be the same gutter bottom variant h6 and we can simply say write a comment now as we have our comments below our comments typography we're going to have the code to write a comment below this typography so to do that let's create a material ui text field which is basically just an input it is a self-closing tag we can expand it in multiple rows and let's give it a few properties the first one is going to be full width this means that the text field is going to span across the entire width of the screen then we're also going to have a property called rows and we're going to set that to 4. usually text fields are simple fields for like name or last name or something like that but our comments can be longer and that's why we can have multiple rows our variant is going to be equal to outlined and we can also have a label which is going to simply say comment we are going to make our text field multi-line and then in there we have to keep track of the value of our specific comment to keep track of the value of our text field we have to create another state so we can say const comment now singular and then set comment is equal to use state in there we're going to pass an empty string because we want to start with empty string now that we have that we can specify a value and the value of this text field is going to be a comment then we can specify the onchange property and to change something we have to get the event like this and we have to call the set comment and more specifically event.target.value that's going to set the value of our text field let's save it and look at it in the browser okay that's already starting to look just a bit better we have our comments and we have our write a comment section of course we still haven't implemented the styles for our containers we're going to do that really quickly now let's add a button below our text field i'm going to create a button that button is going to have a few properties first it's going to have an inline style equal to margin top and then in there we can simply say 10 pixels that's going to separate it a bit from the text field then it's also going to be full width it's also going to be disabled so we can say disabled and it's only going to be disabled if we haven't yet typed in our comment so we can say if no comment our button is also going to have a variant equal to contained and it's going to have just one more property which is the on click handler what do we want to do on click well we want to call a special handle click function which we're going to create right now but before we do that let's simply put something in our button and that is comment great so now we can see that we are missing our handle click let's create it at the top for now we can simply leave it as a blank function const handle click is equal to an arrow function great now we finish the better part of our comment section let's implement our styles to do that i'm going to open up the styles.js and we have to add just a few class names below the loading paper i'm going to add the comments outer container that is going to be equal to an object and then in there we simply want to say display is equal to flex and also justify content is going to be equal to space between below our comments outer container we're also going to have our comments inner container and then in there we can simply specify the height which is going to be equal to 200 pixels we can also specify the overflow y which is going to make our div scrollable so we can set that to auto and we can also give it a margin right which is going to be equal to 30 pixels great these are all the styles that we need for now so let's go back to our comment section and let's actually check it out in the browser that already looks so much better technically we've finished the entire frontend part of our comments functionality now is the time that we connect it to redux and then send that data to the backend and finally create a comment in the database so let's do that right now now let's grab this data from a specific comment and when we click comment let's submit it to redux also i've just noticed that our button is gray and it has to be blue so let's change it right inside of here we're going to give it a property called color which is equal to primary now if you type test you can see it has this nice primary color with that said you already know that we created our handleclick function but we have no code inside of there so let's implement the code right here when we click comment we have to dispatch a new action to our redux more specifically we can dispatch a comment post action our comment also needs to contain the information about who is creating that specific comment so let's grab our user from the local storage i'm going to remove this console log and i'm going to grab our user we can say const user is equal to json.parse and then we can go inside of the local storage and simply call get item user this is going to populate our user from the local storage we've already done this a few times throughout our application now that we have the user's data let's form our comment to include the user's name and also the comment itself let's say something like const final comment and that is going to be equal to a template string the first thing in there is going to be user dot result dot name and then we can say colon and then in here we render the comment so just one more time we are getting the user's name here and we're saying who wrote that comment that user and what is the context of the comment well it is the actual state we are going to write that in that specific text field right in here now that we have the contents of the comment and we can put that here final comment and also as the second parameter we have to say which post does this comment belong to so let's add a comma and let's say post dot underscore id great but as you can see our dispatch is currently not here and also our comment post is not defined so let's fix that first we can get the dispatch by saying cons dispatch is equal to use dispatch hook but now we have to create that action for now let's simply import it even though it's not yet created we can say import comment post and that's going to be imported from dot slash dot dot slash actions forward slash posts great now let's create it right inside of there we're gonna go to actions and then posts and right inside of here below the like post we're going to implement the comment post so let's follow the same structure export const comment post and in this case we'll be getting two different parameters the first one is the value and the second one is the id of the post then considering that data is asynchronous we have to use redux thunk and it has this weird structure which is the async this patch and then after that one more function call like that now how can you know that we are getting the value and the id well we can know that because in here that's exactly what we're passing the comment including the name and the comment and the id great so let's create the actual comment post action we're going to create a try and catch block as we always do now we have to make an api call and that's going to look something like this await api dot comment and then in there we're going to pass the value and the id of course we don't yet have that api comment as we have the like post or delete post or all other so we have to create that and let's do that right away let's go to our api and then index.js inside of here we can even copy the entire like post just above now let's change it we're going to change this to comment our comment accepts two different parameters and that is the value and the id the method of the request is going to be the post because we want to create a comment and the route is going to be forward slash posts forward slash id and then forward slash comment post but of course we also have to pass some value with it so just next to that we're gonna pass an object that's going to contain the value of our comment great we're now ready to make api calls from the front end to the back end but this route doesn't yet exist in our back end so let's create it right away to start creating our backend let's first close all of our tabs just so we have a cleaner workspace and let's collapse our files and folders now let's go to our server and then we're going to go to routes posts.js we can duplicate our like post route and in here it's going to be incredibly similar but just a bit different instead of the patch request it is going to be a post request and instead of the like post it's going to be comment post need to be logged in to be able to comment the post so we're going to leave this here and then also we're going to change this to comment post of course we have to first create that controller and let's import it right there comment post this here is going to be a function on the backend that's going to handle the creation of the comment so let's go to our controllers and our posts.js now let's scroll all the way down below our like post and let's create a new controller that's going to handle the post creation it's going to look something like this export const comment post and that is going to be an async function it's going to accept the request and the response as all of the controllers do and in there we want to get a few values from our front end first we're going to get the id of the post by saying const and then we can destructure the id from rec.params and then also we're going to get const the structure the value but this time it's going to be coming from rec.body now let me specify how is that working i'm going to open the client source api index.js and put it on the side the request for rams is something coming through here take a look we have this id right there and if you take a look at our routes you can see that the id coming in is dynamic and that's what populates the id right here in direct params so where does this value from the reg.body come from well if you take a look at our request one more time you can see that we're passing that object that contains the value and that's what's populating this value that's basically the value of our comment great now let's use those values to create a comment in the database first we have to fetch the post that we have to put our comment on so we can say const post is equal to a wait post message dot find by id and then in there we can simply pass that id finally we're going to go into our post into the comments of our post and we're simply going to push the contents of our comment that is going to update our post but we have to actually update it in the database as well so let's say const updated post is equal to await post message dot find by id and update and then inside of there we have to pass the id we have to pass the new post and we have to pass the options object that's going to contain the message new is equal to true i know this is a long line so let me repeat it one more time we are getting the post from the database we are adding the comments to that post and then we are updating the database so that the new post contains that new comment finally we are storing the value of that post in our updated post variable once we have that we can simply return rest.json that updated post and we can receive that back on the front end great but there is one more thing we also have to update the model of our post so we can go to our server and then models and then our post message inside of here just below the likes we can create the comments part and we can say the type of the comments is going to be an array of strings and the default value is going to be an empty array because by default we don't have any comments in great now we can come back to our front end let's first close all of this go to client side source and then actions posts inside of here now we know that we're receiving something back once we actually call this api so let's retrieve that value we can do that by saying cost response is equal to this and then in here we can destructure and simply take the data from that response for now we can simply console.log that data so what are we expecting to see with this console.log well if our database functionality for creating the comment works and if our frontend is sending the correct data in the first place that means that this data should return a new post and that post should have the comments that are going to be an array and it should have a new comment that we type in so now let's test it out i'm right here on a specific memory page i'm going to click inspect and then i'm going to open the console now we'll keep track of her console and we'll see if her comment gets there let's write something like test and click comment okay something is red and looks like we have the result of null that means that the user hasn't been fetched yet or we haven't properly been logged in so let's close this reload and yeah it's true we are not logged in and we cannot post comments if you're not so we have to properly handle that error let's go back and then inside of here we're gonna check if we have a user so how are we going to solve this well there are a few ways first of all we can in here once the user clicks we can then check if the user is logged in and then if he's not we can disable that but there's a better way why would the user even need to see the part for creating the post if that's gonna result in failure let's immediately remove this from his view that way he's not gonna run into errors so right inside of here we can take this we can check if there's a user we can do that by simply putting our code here opening a dynamic block and we're going to check if there is a user.result.name then we're going to show this so we can say end end and then open a parenthesis then at the end of our div we can close that parentheses and close our dynamic block this code is basically saying if the user has a name basically meaning if there is a user then display this piece of code otherwise show nothing our user is sometimes going to be undefined and we cannot do the dot notation with undefined it's not possible to do undefined.result.name so we have to handle that i'm going to bring the user back and i'm going to say user question mark dot result and then question mark dot name this is the new javascript syntax that's going to allow us to simply not throw an error if the user doesn't exist let's save it and check it out in the browser and would you look at that now we have only our comments but since our user is not logged in he cannot create any that's great he can view but not create now let's sign in i'm gonna sign in with google and apparently even if i'm logged in i cannot see the post creation part so let's see what that is about i'm going to console log our user just at the top right here and our user seems to be null and looks like i've made a small mistake instead of specifying user here we should be specifying profile i'm going to copy this and search for this across the entire code base as you can see we've been calling profile many times and never user i just made a typo so let's go back to our comment section and see if this works right now we can even remove this console log because i'm quite certain it will work and since we're logged in we should be able to see the part where we can create a comment and there we go now we can see this part where we can write a comment if we were logged out we wouldn't be able to see it but now let's see if this comment is going to come through i'm going to say test and click comment now we're expecting akanza log with the post now including the comment and there it is considering that i've used this before it's going to have a few more comments yours should have just a few but there it is our comments are there now we have to fetch them and using redux and reducers we have to bring them back into our jsx view and we can do that like this let's go back to our actions where we left off that's going to be actions post.js and then inside of here we're getting the data about a specific post now including the comments so the question is what do we do with it well we're going to simply dispatch a new action we can say dispatch and we're going to specify the type of our action to be equal to comment also we're going to specify the payload to be that new post with now included comment also after we dispatch that specific comment we're also going to return the data dot comments that means that we're returning the newest comment that's coming in and inside of here inside of the catch we can simply console log the error one more thing see how we've used the constants for all of our action types right there start loading and loading and so on let's now create the constant for the comment as well so right here next to the like i'm going to create a new constant and that's going to be comment of course this is just the import we have to create that constant right here under the source and then constants action types just below like i'm going to create the comment and that's basically just a string again if you're not sure why we're using this for maybe watch some of the previous videos but the quick explanation is that if you scroll down here if you write something like comment here and maybe miss one letter like this comment that's gonna cause a lot of problems in your app but it's not gonna throw an error so you might be able to miss it but like this if we write it as a constant then if you miss just one letter it's immediately gonna throw you an error that's the reason why we do it that part is now done the last part we have to do is deal with this data in our redux and then send our comments back to our comment section where we'll be able to fetch them and then loop over the real comments not just the dummy data so let's do that right away to get this data to our component there's one last step of the entire redux workflow that we have to do first we're dispatching an action then inside of that action creator we are making an api call and finally we have to go to our reducers so let's go to reducers and then post.js now inside of our reducers we also need to pull our comment action type and we have to add one more case to create a new case let's go under our like right there and let's say case comment so what are we going to do on the comment well we're also going to return an object so let's specify it like this and in every object we want to first spread the state and we're going to do that here as well once we spread the state we want to define posts so we can say posts is equal to state dot posts so we want to map over all of the posts and we're going to get each individual post then we want to do something so what do we want to do here well we want to return all the other posts normally i'm going to explain quickly what do i mean by that and then we want to change the post that just received a comment great so we want to return all the posts normally and then change only the post that recently received a comment how can we do that well we can check if post dot underscore id and if that is equal to action dot payload dot underscore id that is our new post that just received a comment so if that's the case then we want to return only that new specific post which is equal to action.payload and in other case we simply want to return a post one more time return all the other posts normally like this and then if the post is that specific post that just received a comment then return it changed with that comment included great so this is how this works we can now remove these comments put this in one line and that is it this is how our common functionality in redux works i know it might be a bit confusing we're spreading the state and then setting the posts but keep in mind we want to return all of the posts and only change the one that just received the comment that is it great so with that we're done with the reducers and now we can actually take a look at our data inside of our comment section component so let's do just that i'm going to close all of our other files go inside of here and now we want to fetch our comments the comments are of course stored in a post and we are already getting a post right there so what we can do is we can initially set our comments to be the comments of that specific post so right in here i'm gonna say post question mark dot comments okay so now we're getting our redux data from the backend right in here and putting it in our comments and of course we have to change it right there so we're not gonna simply say comment i we are going to return the c the comment of course so for every comment we want to return a comment inside of a typography let's save it and check it out and would you look at that we have our comments i've been there last year the best experience ever and we have all of the comments we can scroll through and read them now let's sign in as well okay as we're signed in we can now write a comment and the functionality should be fully functional so let's say grade memory okay let's try seeing great memory a few times and nothing seems to be happening but if you reload the page you'll be able to see that we clicked it quite a few times so we just have to make it update immediately as soon as we leave the comment and that's what we'll do right now but with that said you can see the comments actually work you can write a comment click comment right there and you just left it on this specific memory let's go to another one let's go for example to the eiffel tower let's write something meaningful looks great at night great and let's comment it and as you can see nothing happened right away but if we reload the comment should actually be there and there it is okay so now let's make it update automatically we can do that by immediately receiving all the new comments from the dispatched action if i go into this specific action creator you can notice that we are returning all the new comments and we can actually make use of that let's make this function asynchronous and right inside of here we can say const new comments and new comments are going to be equal to a weight dispatch great so now we can use those comments more specifically to set the comments to new comments that's going to update our state of comments and then render them down immediately what we can also do is we can set our singular comment that's the data inside of the text field we can set that to be an empty string and that should clear it out so let's check it out anybody else been here let's do something like that leave a comment and take a look amazing we can successfully post comments on our memories now what if i keep adding comments like test and then maybe one more let's add test one as you can see test one has been added but you cannot automatically see it which is not a great user experience you have to scroll down so let's make it scroll automatically you might think that you're gonna have to use some external libraries or that it's gonna be hard to do it but it's not really that hard we just have to know how to use refs so we're importing the usref hook right there and right here we can say const comments ref is going to be equal to use ref so we've just created this specific reference that we're going to hook onto a specific element more specifically we are going to create an empty div just below all of our messages so right here we can create a self-closing div like this and the only thing it's going to have is going to be a ref equal to comments ref this is going to be our anchor point we're always going to scroll to this specific div because we know that that div is at the end of all of our messages so let's scroll up when do we want to scroll well we want to scroll once we add a new comment so right here let's create the functionality to scroll down we can do that by saying comments ref dot current dot scroll into view i'm missing an n here and you call that as a function pass in an object and then in here we can say behavior is equal to smooth that's going to make it scroll slowly to that specific point and with that our scroll should be done let's check it out let's add a new comment let's do test two and as you can see it just scrolled let's try adding a few more test four it scrolled as well great this functionality is now done last thing that we can do is make the username bold and leave this as it is we can do that right inside of here by splitting our comment into two parts more specifically we can say comment dot split and we want to split it by that colon and we want to get the username so if you do 0 this here is only the username now that we have just the username we can put that into a strong tag and that is going to make the text bold so if i do it like this and just below we can now get the second part which is the actual comment so we can say c dot split we want to again split by the same thing and in here we want to get the first part which is the actual comment on the bottom part make sure not to put the space in here great let's save it and check it out great that works now we can differentiate the username from the comment this is a seemingly easy feature that we just implemented but it's really going to add a lot to the entire application our memories project really needed the comments section because now people can comment on each other's memories and share their stories but that's not it for this video i've decided to do one more thing some of you guys requested of me in the comments and that is to fix the speed of liking something right now if you click like it's gonna take maybe a second a second and a half or maybe four to five seconds in areas with slower internet connection so if i click it notice how long is it gonna take yep that was quite a long pause so what we're going to implement for the end of this video is the ability to immediately give the user feedback once he likes something the actual liking on the backend is going to take 2-3 seconds but we can immediately display the action to the user let's do that and this is not useful only for liking you can use this technique with everything where you want to give users the quick user feedback if you appreciate these little tips that i like giving to you definitely make sure to like and comment down below comment if you'd like to see the entire map of all the memories implemented in the next video to implement our let's call it quick liking we can go to client source components and we're going to go to posts and finally a singular post component from here we can see that we have some imports that we're not using so we can delete that right here get post and we can also immediately import use state from react because we'll definitely be using that great so now let's see what do we have to do right now we're getting the post passed through props and that's fine we're then using that post to find out the length of the likes in that specific likes array and then based on that we're showing our likes but we can make that just a bit better first of all we're going to implement a new state field called likes and of course it's going to have a set likes which is going to be equal to use state and then inside of there we want to immediately set that to the post question mark dot likes so we're taking the same value from our post right there post question mark that likes and we're setting that into likes so so far not a lot has changed but there is a specific reason why we need to do that because now we can set them again we can reset them we can change them because now we have this setter function so we're going to scroll down and find where we're actually liking something here's the delete and right here is the like button so right now we are doing something on click but we need to do a bit more stuff so i'm going to copy this and simply create a new function called handle click we're going to use that function above right inside of here so right here let's create a new function const handle like is equal to an async function like this and then let's simply paste what we had of course we don't need this callback function it says our handle like is not being used so let me see why i called it handle click a more appropriate name would be handle like great so now we've changed nothing we've added a new handler function which is still doing the same thing it used to do before and we also just added these likes which again is not being used so now what can we do to start using them inside of here we're going to add an if check i'm going to copy this entire part right there pose.lice.find and then we're checking if the like is equal to to the google id or the result underscore id we are basically checking in this whole thing did the current user like the post so we can say if this and that's basically saying did the current user like the post or not usually when you have lines as long as this one it's good to put them to a specific variable so let's say const has liked post and that is going to be equal to this now that we have this we know that that's going to be a boolean value and we can say if has like the post then we want to do something else if the user hasn't liked the post then we want to do something else so what do we want to do if the current user has liked the post well we want to set the likes to be equal to post dot likes dot filter inside of here we get a specific id and we want to filter out the id of that specific person so we can say if id is not equal to and that's going to be in parentheses user question mark dot result dot result dot google id or we can also have user question mark dot result question mark dot underscore id so we're basically simply filtering out the like because if the user has liked the post and he or she clicks the button again that means that they want to unlike it but now i figured out we're mentioning this part quite often so i want to take that entire part and put it in a new variable let's copy it and i'm going to call it something like const user id and that's going to be equal to all of this we no longer have to repeat it i'm going to put it above and we can use that id in a few places we can use it right here because you can notice is the same thing we can also use it right here that's also the same thing and we can also use it right here because it's the same thing this was a great little lesson where we used two new variables to simplify our code and make it more readable now everybody can understand that this whole part is either getting the user's id from google or a normal id from the database and it's storing it in the user id variable and then in here we're simply figuring out if the user has currently liked a post or not finally if the user has liked the post that means that they want to unlike it and then we filter out their specific like but if the situation is different if they haven't liked it we can say set likes equal to we spread all of the current likes and then we want to add one new one and that is that same user id variable we created right here and why is this faster than simply updating the database immediately because updates to the database are asynchronous and they take time but this is gonna happen instantly finally we need to use our likes as you can see they're not currently being used right here we have to exchange every single place where we mention pose that likes and simply use our likes so that's happening here you can do control f and then find pose that likes and simply replace that with likes then you can click enter a few times and it's going to fill that for you there we go so in all of the places where we used pose.likes you simply have to switch it to simply likes there might have been a lot of code in here so if you mess something up that's completely fine you already know where the link to the entire github repository is so make sure to copy the file if it's not working for you okay before we finally take a look in the browser i think we also have to replace this part here with only likes and let's check it out okay let me try to like something that was instantaneous take a look at that i can like and unlike all the posts incredibly quickly and if i refresh the page as you can see it's going to be updated in the database i can try unliking everything now and then we're going to reload the page and as you can see everything was successfully stored in the database but now the feedback that the user receives is instantaneous look at that i would say it's less than 100 milliseconds it's basically instantaneous at this point everything seems to be working great and the last thing that we have to do to make this a complete project is to deploy it on the internet so you can share it with your potential employers and friends so let's do that right away to deploy the back inside of our application we're going to use heroku when you log in you should see something similar to this at the top right you can see a new button where you can create a new app we can choose the app name i'm going to use something really random like mirn memories js mastery that should be available and you can choose your region and then in here you'll get all the instructions of how you can deploy your application using the heroku cli the first thing you have to do is download and install the heroku cli for your own operating system after you do that you can follow my steps before we start writing the commands we just have to make sure to change just a few things in the code first of all go to the package.json off the server side and then in there change this from nodemon to simplynode when you run a server you don't have to constantly restart it so we're only gonna need node and then the second thing is if you don't already have it make sure to rename this to dot proc file we need to have the dot proc file where we say web is equal to npm run start great and the last thing just so we know if our server is running we can go to our index.js and then in there we can create the app.getrout app.get it's going to be just slash and then in there we can get the rec and the res and we can do something like res.send app is running this is just the message that we're going to get in the browser so that we know that their server is running okay with those changes ready i'm going to close these files and let's follow the process run the heroku login press any key that's going to prompt you to log in after you're logged in make sure to run heroku git clone and make sure that you are in the server directory so you need to be in the server directory the process for you might be just a bit different but just follow the steps you need to be in the server folder run the heroku remote to add and finally we need to push all of our changes by running git add we can also do a git commit and finally git bush heroku master this is going to deploy all the changes so that your server is going to be live and deployed on the internet okay we got a confirmation message verifying done we can clear the terminal and expand our browser a bit now if i unzoom this a bit on the top right side you should see open app once you click that at the top left you should see app is running that means that we are ready to take this url and connect our frontend to it so copy that url let's go back to our code this time to the client side we're going to go to the client source api index.js and then in here you're going to replace this base url with your own new deployed server url that is one thing that we have to do and the second thing is that you have to go to the public folder and then in here you have to add one special file we have to add the underscore redirects file so just underscore redirect then you can put forward slash and then the asterisk finally forward slash index.html and finally 200. this is the only thing you have to have in this file once you do that you can close everything and we're now going to cd back into the root and then finally cd into the client side when you're in the client side we want to build out our entire react application by running npm run build while our build is running we can go back to the hostingers dashboard to visit it you can click the link down in the description and then log in or simply go to hpanel.hostinger.com if you purchase the premium shared hosting then you should be able to see it here under setup and you can click this yellow setup button then you'll see a startup process you can click start now you're going to be asked a few questions but the most important thing here is at the bottom there's going to be a text that's going to say skip i'll start from scratch so you can click that to fully set up your own domain after you've done that you should see a page that looks like this your domain name is going to be here and you'll have a lot of different tools that you can use right here on your disposal there are two different things we need the first one is ssl certificate so you can type ssl click right here and then the only thing you have to do is simply click install ssl and there we go ssl is being installed this is going to allow https security as soon as i've reloaded the page the status changed to active it cannot be any simpler than this then we can go to dashboard and the only thing we need is going to be the file manager right here let's click it inside of a new window you're going to see your hpanel dashboard and you can go to public underscore html there for now you'll see a default.php site which you can delete and then you can go back to your code and open up that build folder we've created once you open it up in your file explorer that's going to be memories and then client you should be able to see your build folder right here the only thing you have to do is open it up and then simply drag and drop all the files right inside of here there we go in just a few seconds they were uploaded now we can go back to your hosting panel reload the page and we can type our domain name in the navigation bar and simply press enter our memories are loading and we can see the posts which means that our front end is not only hosted online but also connected to our backend which is also hosted online this works perfectly we can paginate we can see all of the great features that we just created in this video it's so good seeing the application you've been working on for quite some time now being almost done of course there are always some new features that you can keep adding to your applications and keep improving them that was it for this video if it was helpful definitely feel free to leave a like and comment and if you'd like to build more projects with me make sure to subscribe and turn on the bell notifications if you turn on the bell notifications you can be sure that you're not going to miss the fifth part of the mirn series when i upload it with that said thank you so much for watching see you in the next one and have a wonderful day [Music]
Info
Channel: JavaScript Mastery
Views: 691,181
Rating: undefined out of 5
Keywords: javascript, javascript mastery, js mastery, master javascript, mern stack, mern stack tutorial, react full stack, mongodb tutorial, full stack, mern stack tutorial 2022, mern tutorial, mern stack project, mern app, mern app with authentication, react node express mongodb, mern stack traversy, mern stack tutorial for beginners, mern application, full stack mern application, mern stack crash course, mern stack react, mern stack social media, full stack mern
Id: VsUzmlZfYNg
Channel Id: undefined
Length: 448min 29sec (26909 seconds)
Published: Tue Mar 22 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.