Full Stack MERN Project - Build and Deploy an App | React + Redux, Node, Express, MongoDB [Part 2/2]

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everyone and welcome to the second part of building a full stack marin application our memories project if you haven't watched the first part it is going to be linked in the description make sure to watch it first and then come back these two videos alone are going to teach you how to effectively use the mern stack to build projects as i mentioned in the first video i initially planned on putting this as the paid course but i later decided to release it completely free for you guys here on youtube so to support this video leave a like comment and subscribe it shouldn't take more than a few seconds but i really appreciate it on another note some of you in the comments requested me to add some extra features to this app things like authentication pagination and more if you'd like me to create a third part of this series where i add one of these features you requested make sure to like comment and subscribe if this video reaches around 5 to 10k likes we are recording part 3. with that said let's jump straight into the project 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're 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 great 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 0 then 0 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 0 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 three 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 gonna immediately return something notice how it didn't put curly braces there but rather just normal parentheses inside of here we're gonna return yet again a grid but this time of 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 gonna 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 are 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 gonna be core it's gonna 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 horiz 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 typography one 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 gonna copy this one is gonna be of body two 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 gonna 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 that 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 that 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 body two 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 returned 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 dot 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 gonna 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 going to 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 count 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 svg 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 it's going to have request and response first thing that we want to do is we want to extract that id from request.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 dot 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 that 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 res.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 are 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're saving in the updated post or you can call it post data that's going to be equal to an error 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 are 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 dot 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 the 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 going to 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 gonna be good and now i'm gonna 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 going to 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 going to 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 1 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 going to call it at the end right here i'll save it and go back and see if it works okay i'm going to 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 clicking 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 gonna 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 posts and make sure to have this line that's going to 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 backend if only changes you made were on the back end 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 going to 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 all together 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 tax we can even copy this one and then bring it above the card 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 uh let's add a second exclamation mark and in here i'm going to change the tag to 2030 again click submit 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 post.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 consolog 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 gonna be line four and take a look cannot read property id or underscore id from action dot pay lad 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 going to 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 gonna 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.rams 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 initiated 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 deleted and then we're gonna call axios.delete we pass in the url and forward slash we also pass in the id same thing with it 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 and 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 that 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 uh delete post which we just created from dot 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 backhand 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 gonna 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 copied 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're 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 gonna 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 await 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 await 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 likecount 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 going to save that and let's move on to the front end 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 going to 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 are 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 pause that 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 um 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 gonna 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 nb 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 moved 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 going to search for spacing is equal to 3 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 to 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 xs 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 gonna 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 delete 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 gonna do is in here instead of the 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 a 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 project 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 replication 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 10 000 we don't want to 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 our.env is not going to be saved on our github what i like to do is i like to do 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 the last thing we have to do is of course deploy it to the web deploying backend is going to be just a bit harder than deploying the front end so let's start with that for deploying the backend application or rather the api we will be using heroku heroku is great for hosting servers you can visit heroku.com and then you can sign up or log in just at the top right i just logged in with my account and i see i already have some projects right there but we're gonna start with a completely new one so this page should be empty for you if you're using heroku for the first time if that is the case you can click this new button at the top and then we're gonna say create a new app after you do that it's going to ask you for the app name we're going to say something like memories dash project just like that and then below you can choose a region now i'm going to click create app looks like our app is generated and now all you have to do is follow the steps right here first you have to download and install the heroku cli you can do that if you click that button and there you should be able to see it you can install it for mac os linux ubuntu and also windows so just go ahead and choose your own installer after you install it i think we should be able to go into the console and type heroku-v this is going to give us the version we are running now let's do as they say roku login in here heroku login of course you have to quit your application and then you have to be located in the server folder i'm gonna run heroku login and then it's going to say press any key to open the browser to log in it's going to prompt you to log in to heroku cli you can do that and then after it says logged in you should be able to continue with the process you don't have to cd into my project because we are already inside of the server directory if you're not make sure to navigate to there and when we are in there we have to initialize a git repository so you can do that by doing get init finally let's follow the next command and that is going to be heroku get remote and then you have to add that to your remote again just copy and paste the commands you're getting right here now the process is going to be just a bit different we have to modify a few things before we add everything let's first start by our index.js in here i'm going to add one greeting route so as soon as you come to your application we have to have something so that's going to be app.get and then in here that's going to be just slash and we always have rec and res and then in here we're going to do rest.send and let's do hello to and this is going to be uh memories api like this great this is just something we're going to see once you go to the actual deployed version now we do have to make a few more changes first you can see all node modules everything is added to your get as you can see 1000 changes you don't want to do that you want to move your node modules away from your github so in here i'm going to create a new file inside of the server folder and that file is going to be called dot get ignore like this and then in there we're simply going to add our node modules now you're gonna see this is gonna be removed and from a few thousands now we have only ten files to be uploaded usually you would put the dot env file right there but we won't be uploading this to github we will only be pushing this to our heroku and in this case heroku has to know about our env so we're going to leave this right here and we're going to remove the port because heroku is going to add the port themselves so the only thing we need is connection url if we go back to the index.js let me explain what i was saying in here this process that env variable is going to be populated immediately by heroku finally there is one file we have to add and that file is called proc file so in there you can specify proc file with the first letter being capital save that and there we can type web npm run start this is going to enable heroku to start the application as soon as it is deployed great i think that's it i know we changed a lot of things but sometimes during the deployment process you have to make some adjustments i think that's going to be it so we can close all files and now we can finally push it so we have to do git add dot then we have to do git commit and then just do any commit message in here they say make it better and the last thing is get push heroku master so i'm just going to copy and paste that and there we go let's hope it's going to be deployed it is going to start building right now there we go installing the dependencies installing node modules building and hopefully it's going to be up and running really soon as you see build succeeded and there we go it says it's released we can go back to our browser and then under the overview you should be able to see that our project was built successfully and that it is deployed now if we go right there to the open app you should be able to see it i'm going to click open app and there we go at the top left we get hello to memories api this doesn't have to look pretty because this is just data remember if we go to forward slash posts we should be able to see all the posts that we have currently we have four posts in our api that are being fetched from the database to finalize things we have to go to the client side inside of the src and then inside of our api in here we have to change this url to stop fetching things from localhost 5000 because that is local and we have to copy this whole url memories project and then forward slash posts just like that in here you're going to have to type your own thing just copy and paste it from your browser when you load in the heroku project now if we save this we should be able to go back and possibly see everything in the app as you can see here are our projects and now i'm going to delete this test one and it should be immediately reflected after refresh in here in the actual deployed api and there we go there is no fort post for testing purposes let's add one more post and that's going to be test test test and test i added the test image as well i'm going to click submit and the post is added you can see it right there but if we go back right here and if we collapse all of these things you should be able to see it was immediately reflected in our live deployed backend and we can even know that it's not picking things from our local backend because in here take a look local backend is closed it is not running right now that means that the whole backend is running on this live deployed api on heroku and finally the last thing for this app to be fully deployed is to get rid of this local run of the client side as well so we have to deploy the client side as well deploying client side is going to be easier than deploying the back end we will be using netlify it is a great tool that allows you to deploy your front-end applications in a matter of seconds you can log in or sign up and then in here we'll be able to deploy our front end this is going to be empty for you i already have some projects but you can go ahead and click sites right here after you do that you'll see something that looks like this this should be empty for you but take a look at this empty rectangle at the bottom want to deploy a new site without connecting to git drag and drop your site folder right there and that's what we're gonna do going back to our application i'm going to stop the server from running and then run the mpm run build right into our client folder this is going to generate a built version of a react application that we'll be able to deploy on netlify it is going to take some time i'm going to skip this video and we'll be right back our build is now generated you can see right here in the client we have access to this build folder now you're going to right click it and then click reveal in finder or open file explorer on windows after you do that your folder is going to be opened and the only thing you have to do is drag and drop the build folder right inside of here that is deploying right now and maybe even as i speak this should turn green there we go it took about three seconds now you can click this and that's going to take you to deployed react application there we go our posts are right here our application is deployed we are no longer dependent on running our servers we can completely close this we are not running anything this is live on the web and we can even change the url so if you go into domain settings and then options you can edit the site name right there so let's try with something like memories underscore or just dash app looks like that is available and there we go frontend is deployed back in this deployed they are all working together for us to be able to create edit delete and update the posts that's it for this video make sure to like comment and subscribe and let me know in the comments if you'd like to see a part three to make sure not to miss the next video subscribe and more importantly turn on all notifications by clicking the bell icon stay safe and see you in the next one
Info
Channel: JavaScript Mastery
Views: 246,243
Rating: undefined out of 5
Keywords: mern stack tutorial, mern stack, mongodb tutorial, mern stack tutorial 2020, react js, mern stack project, web development, reactjs tutorial, reactjs tutorial 2020, mern stack project from scratch, mongodb tutorial for beginners 2020, react tutorial 2020, react full stack tutorial, web development 2020, react node express mongodb, learn javascript, mern tutorial, mern project tutorial, mern project 2020, mern projects for beginners, mern application
Id: aibtHnbeuio
Channel Id: undefined
Length: 81min 57sec (4917 seconds)
Published: Fri Nov 06 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.