Full Stack React Node Project | Build a Notes App from Scratch for your Portfolio

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so in this project we're going to build a Notes app where we can add delete and update notes we will build the front end and react the back end user node we will store our nodes to a postgres database and we will build everything from scratch if you would like to try this project yourself before following the tutorial you can head over to code coyotes where you will find starter code the final code and some hints and tips for you to get started okay so the first thing that we're going to do is get our project structure set up I've just got a terminal open here and I'm on the desktop and what we're going to do is get a new folder called Notes app so this is going to hold the code for our UI and also the code for the back end and once we've done that we're going to go into the notes app directory and then we're going to create a new react app using MPX create react app and then we're going to give it a name and give it a template of typescript so this just sets up a boilerplate react app for us using typescript and then go ahead and hit enter and it'll take a few minutes to install all the packages and once that's done what we want to do is open up the note app folder in Visual Studio code or whatever IDE you prefer so a bunch of end Visual Studio code you should see that the notes app is at the top level and within this we have the notes app UI in the second half of the course we're going to have a note app server in here as well just to keep everything together let's go ahead and open a terminal and we're going to make sure that we're in the notes app UI directory and then we'll call mpm start so this will just start up the front-end development server and open our app in the browser so all being well you should see the the app start so it's got the react logo that's spinning and it's got some Styles and stuff in here too but for app setup we're going to jump into the IDE and we're going to go into app docs in the search folder and we're just going to delete everything in here and this will be our starting point okay so the first thing we'll do is we'll put some of our UI components in place so this will just be the general markup on CSS with any javascripty stuff and it gives us an idea of how we want things to look without having to worry about API calls and see when things to the database at this stage so I've got the finished code running in the browser here just to show the end outcome that we're going for as we go through the code I'll reference different bits and pieces in the browser to help visualize things a bit easier it will go into up.tsx and we'll just create a new component we're going to make sure that we import our style sheet from up.css and the first thing we're going to add here is our date of the class name of app container so this is going to help position our form and the CSS grid that we're going to use for the notes So within this we'll open our form tags and we'll add an input for the title so this is the title of the note that the user can enter and a lot of text there for a note contents we'll set both of these fields to required to take advantage of the browser's validation messages that they will give us if the user tries to submit a form that doesn't have both these fields entered and at the bottom of this form we'll just add a button this will be of type submit so when this button gets clicked it's going to submit the form for us off to the right we're going to have a div that's going to hold our notes as we said before this is going to be a CSS Grid or finesse we're going to have an array of notes but for now what we're going to do is just add the markup for a single note and we'll add some more later on just to see what it looks like so for final note we're going to have a header so this will have the delete button that sits off to the right hand side we're going to display whatever the title is that the user entered for now we're just adding in a dummy title and we're going to add the content to the user entered and at the very bottom we'll just export our component okay so we'll open a terminal and we'll type npm start and this will open the app and the browser and as you can see on the right hand side here things aren't looking too good at the minute but that's because we haven't added any of our Styles so if we jump into app.css we'll apply the styles to the classes that we added in the previous bet so you can grab the style from the link in the description if you would prefer to copy and paste it then and just follow along pretty walk through which is probably easier than typing everything I otherwise feel free to follow along and pause the video when you need to just remember that these Styles don't have to be perfect it's just an example for learning so in app.css the first is we'll just add some styles to the body so we'll give it a gray background and we'll just add a margin around the outside just so our app isn't pushed against the browser window Edge and then the next thing we'll do is we'll style our app container so we're going to build this mobile first which means all the default Styles will apply to mobile screens and we will use the media queries to make sure the things look good on the bigger screens this is just one approach and you do not have to do it this way if you don't want to but it's typically harder to design for mobile screens sometimes it's better to get that out of the way first from mobile screens we want our app container to default to a single column that means means our form and node script will stack nicely on top of each other and then we'll just add a media query in here to say that for any screens that are bigger than 600 pixels then we want to use two columns so we specify this with the grid template columns our first column is going to be 200 pixels and that'll hold the form on the left or in the First Column and then we'll say one fr4 the second column so this just means take up the rest of the available space and and then we'll give it a gap of 20 pixels to just add a bit of separation between the two columns next we will style our note grid so this is going to help position our notes so let's say that this is a grid and then we'll specify the grid template columns this piece of code does is it says that each item in the grid must be a minimum width of 250 pixels but it can expand up to take up the rest of the remaining space so as we expand the window and retract the window for different screen sizes then things will resize to fit automatically don't worry if this doesn't make too much sense right now we will see it working in a minute once we get the rest of our Styles in and here we'll also specify grid Auto rows and let's say each row has to be a minimum of 250 pixels and then we'll just set the auto property which means that it can go as high as the content allows so since each of our notes can be different sizes based on the content that the user adds we want to make sure that each row at least will stay the same size just so it doesn't look too funny so we'll see this work in a minute and then again we'll just add a gap of 20 pixels to it as well just so we have some spacing between the notes so next we'll style the note item so in here we're going to use flexbox by using display flex and we'll set the direction to be Flex Direction column so what this does is it Stacks all our elements so the header the title and the content and a vertical layout and it just makes it easier to position the child elements and we'll just add smaller basic Styles in here such as a border as some padding a border previous and a background color and we'll just add a box Shadow as well just for an extra nice effect next we'll add some styles to our notes headers so this holds our delete button and we'll just make this a flex container and we'll say justify content Flex end which pushes everything to the right of the container so that helps position our delete button where we want it to go and then for the button itself we just want to add some studies to make it look nicer so we'll just change the font size take away the background take away the border and we'll give it a Max width of that content which means the button should be as big as the content allows which in this case is just a single character so that's fine and we'll just remove the margin from the H2 header so we don't really need a margin in here because the flex box that we added to the note item is going to handle the spacing for us so by taking away the margin and make sure that things are spaced nice and evenly so next we'll just add some stylus to the form on the left in the First Column again we'll just say that add the note form is going to be a flex box container and then we want to arrange items in a column so we'll say Flex Direction column and then we'll add a gap of 20 pixels as well just as we've done with the rest of the app and then we'll just add some styles to our text area and our input just to make them look a bit nicer so let's add a border add some padding and we'll change the font size a bit and the same with the button will just change the color and add some other Styles as well okay so now we have our lesson please what we'll do next is we'll add dummy notes to your app component just to make sure our CSS grid is nice and responsive so to do that we'll jump into app.tsx and then we'll import the use State Hook from react just inside our app component we're going to store the notes within the use statehook so every time you have something that can change on the UI it's a good idea to put it instead so we'll initialize this with a dummy array of notes so for each note we're going to have an ID a title and a content and then just copy and paste this a few times it doesn't matter too much what values you put in it's just to give us a few notes so that we can see what things look like in the browser another way to think of what we're doing here is to pretend that we've just called the API and we have gotten this data back in response and then we've just put it into the shape of this data is going to be similar to what we'll get back from our API requests when we eventually build out our backend okay so now we have our array of notes instead we can do is open our notes grid we're going to use the map function to display the current markup that we currently have for each of the notes in the array so because we have four notes and our notes array and the map function is going to run four times and display this markup for each of the four notes and instead of the hard-coded title and the hard-coded content we're going to take those values from the note instead and that's basically it if we look at the browser we can see we have our four notes and it's taking the values from the object and the array so if we change our screen size here you can see that the notes are responsive based on the size of the window and if we go to the smallest window which will simulate the Mobile screen you can see our form Stacks vertically above our note grid okay so one enhanced one we're going to make before we carry on is to give our notes a type using typescript so there's a few benefits to this which we'll see in a moment so just outside of the app component we'll create our new type and give it the properties that our note has so we'll say ID is going to be type number title is going to be of a type string and content is going to be of type string so once we've done that we can use this type in our use data so we'll open some angle brackets and we'll paste our type in and say it's a note array so this is helpful because now down in our notes map where we display the notes if we hover over the notes variable you can see what type it is and if we hover over the note we can see it's of type note what this means is it gives us some good intellisense because if we type note dot it'll open up the pop-up that shows us what properties are available to us as you can see we have the content ID and the title this is helpful as it means that we can easily see what properties we can access and what types those properties have and it just helps with catching bugs earlier and with productivity okay so now we have our UI in place what we'll do is add the functionality to the form that lets us add a new note so we'll do this just for the UI for now and then we'll add the logic to persisted to the back end later on after we built the back end so in react whenever we are working with forms what we need to do is add a state value for each of our form inputs means that react can control those inputs and it makes it easier for us to get the values and do stuff with them so since we have two inputs a title and a Content field we will add to State variables called title and content and then for the input for the title we will say that the value is equal to whatever the title State variable is and then we'll add an on change event to this input that changes the title State value based on whatever the user has entered and then for the text area we will just do the same so we'll say that the value is going to be content and then we'll pass in a function to handle the unchange event and update the state with whatever the user has entered okay so once we've done that next we need to add a function to handle the submit of the form so we'll create a function and we'll call it handle submit and this is going to take in the event as a parameter and we have to give it a type or else type script will complete into us so we'll say that this is of type form event and we'll say event dot prevent default so this just stops the form from trying to post and refresh the page which is the standard behavior for a form but we don't want that to happen and then we'll just log out our title and our content after that in the form tie what we want to do is wire up this new function to the on submit event that happens within the form so we'll say on submit and then we'll pass in a function that calls our handle submit function so now if we open up the console in the browser and if we add a title and add the content into the content field and click add note you can see in the console that the values have been logged out okay so now that we know what the title and the content State values are going to be whenever the user clicks on the add note button we can take those values create a new note and then we'll save it to our notes array and this will add it to the UI so the first step is to create a new object and then we will say this is of type note and because we're using typescript and give our object a type we can take advantage of some nice intellisense things here to populate the object for us so this is Handy if you have quite a large object with many properties that helps you fill them all out without missing any so for the ID it doesn't really matter at this point what we put in for the ID because at the end of this the ID will come from the database and our backend but for now we'll just take the ID as being the length of the current notes array plus one and then we'll add our title as whatever the user entered the same for the content now that we have a new note object we want to call the set notes function which will update our state and we want to pass in a new array and the first item in this new array is going to be the note that we just created and then we will pass in the rest of the notes using the spread operator so what this does is basically copies the old notes array and inserts the items into this new array that we're creating we will also reset the title and the contents did to the empty strings so this is just good user experience so after they add a new note the form will clear down and then they can add a new note again if they want to and that's it so if we jump over to the browser and if we add a title and add some content and then click add note our new note will appear at the top and our form will clear okay so what we'll do next is we'll add the functionality to update a note so if we look at the finished app when the user clicks on a note what we want to do is we want to populate the title and the content fields in our form of the values of the node that the user selected and we also want to update it so that these buttons appear so we have a save button and a cancel button and then obviously if the user changes either the title or the content build enter form and hit save then we want to update the node with whatever the new values are so for this part we're just going to update it on the UI and then we will persist it to the back end later in our code the first thing we'll do is we'll tidy up some of our existing stuff a bit so we will delete our console log statements we don't need those anymore and then we will rename the handle submit function to handle add note this is because we'll create a handle update node function in a minute so don't want to confuse our cell next what we need to know is the note that the user clicks so that we're able to update the title and the content with whatever values are in that note so to do this we're going to store the collected note into state so we'll create a new state variable called selected note and then this is going to have a type of note we say null as well because we might not have a selected note so this means it can be empty so in here we will set the default to null next we're going to add a function that handles the event when the user clicks on a note so we'll call it handle note click and this is going to accept a note which will be the note that the user clicked so in here what we'll do is We'll add the note that user clicked and we'll save it to State using the set selected note function and then we'll set the title and we will set the content to whatever values come from the selected node so this will update our form with the existing values and then down in our note item on the top octave what we'll do is We'll add an on click function and we'll call our handle node collect function and we'll pass in the note so since this is within the map function each node will have this on click function added to it okay so now if we run our app and if we click on some of these notes we should see that our form updates okay so now we have a way for the user to edit a note we need to take whatever they change in the title and change in the content and save it into state so I will do that is we'll create a new function called handle Update note and in here we will do event.prevent default so this just prevents the form from submitting whenever the user clicks the save button which We'll add in a second and then we'll add a conditional in here using an if statement basically says if we don't have a selected note then just return out of the function if our function runs without a selected node it will cause errors so it's good practice to check and hand handle this scenario early on next we will do is we'll create a new note object so this is similar to what we have done before and here we're going to set the ID to be the ID of the selected note and then we're going to take the title and take the content from our form so these values will be whatever the user has edited after they have selected a note and next what we'll do is we will use the map function to create a new array and we will update that array with our new note object so as the map function iterates over the array of notes we're going to check to see if the ID of the note node the map function is on is equal to the ID of the node that the user selected if it is then we will return the updated note otherwise we return the current note so so remember that the map function will iterate over an array and run this function for each object in that array so anytime we return something that is what's going to be returned in that index of the new array so once we have our new array with the updated note added to it all we have to do now is set it to state so we'll take this array and call the set note function that updates our state and then we'll just update the subtitle um depth content State variables to be empty strings and then we will set the selected node to be null so this just resets our form after we've updated the array and while we're here we will add a function to handle the cancel button click so this doesn't take too much all we're doing in here is we're just setting the title and the content to be empty strings and setting the selected note variable to be null so this just resets our form and our selected notes did to be null now that we have those two functions that handle the update and handle the console we can add in our buttons for whenever we have a selected note so what we can do is down in our jsx we can just do some conditional logic to render the different buttons based on if we have a selected note or not so if we do have a selected note we're going to display the save button which is going to have a type of submit and we're going to display a cancel button which we will call our handle cancel function from and if we don't have a selected note we'll just display the signaled Button as we currently do and we can do similar to the on submit function within our form so currently we just have it so that we call the handle add note function whenever the button is clicked or over to form and submit it but what we want to do in here is use a conditional to say if we have a selected note then we want to call the handle Update note function otherwise just go ahead and call the handle add note function so if we start up our code and try this out you can see if we click a note and then we change some stuff and click on save you can see the note gets updated so just before we move on we're going to add some CS to study these buttons just to make them look a bit nicer so if we look at the code that we just added and our jsx you can see we've added a div with a class name of edit buttons that wraps both our buttons so this edit buttons is going to be a flexbox container if we jump into app.css we will add our Styles in here so if you prefer not to type out a bunch of CSS you can have a look for the link in the description where you can go and copy and paste it so we'll add our edit buttons class in here and then we'll say that this will be display of flags to make it a flexbox container and then we'll say justify content space evenly so this spaces our items out evenly depending on how much space there is so for different size screens our buttons are going to resize correctly then we'll add a gap of five pixels in here as well just to help with the spacing then for each button the thinner edit buttons Dev we want to say Flex one so all this means is that the buttons will expand to take up all the space that's available to it so sometimes depending on the text or the content of a button the button will only stretch to fit that content by saying Flex one just make sure that the buttons always stretch to fill the container and then we will just add some styles to the cancel button by using the last of type so this just selects the last button and our edit buttons Dev will change the color to be red just so that it's different from the save button the last thing we need to do before we go and start building out the back end is to add the logic on the UI that let's just delete a note remember we added a little X or delete button to each of our notes when we click this we want the node to disappear from the UI so if we jump back into app.tsx we'll start by creating a function for this and we'll call it delete note this function will take the event and we'll also take the note ID as we need to know the ID of the note that the user has decided to delete and then and here we're going to say event.stop propagation but this means is because our delete button is within a note and we've added an on click event to the note itself it stops the delete note event from interfering with the event we added to the note it's only necessary to do this when you have nested on click events okay so next we're going to take our current notes that we've saved instead and then we're going to use the filter we're going to use the filter function on it to remove the note that has the ID of the note that the user has decided to delete so the filter function is similar to the map function in which it iterates over an array and applies the function we defined to each item and array so it's going to return all the notes that don't equal the ID of the note that was passed into this function and then it's going to return an array at the end of the new values and assign it to the updated notes variable that we created and then all we have to do is see if this new array to State using the set notes function once we've done that we will add on click event to our delete button and then we will call the delete note function and then we'll pass in the event and we'll pass in the note ID which we get from the note and if we look at the app in the browser and if we click on the delete button for a given note you can see it disappears from the UI okay so now that we have all the bits and pieces on the year and added some interactivity next we'll add the back end that lets us persist the notes when the user adds edits and deletes them so to start this what we're going to do is create a new folder in our project so this folder will go at the very top level and we'll call it Notes app server even though it looks like we're putting the server code in the same folder as the UI it's completely different code it's going to run completely independently so we just put these two things together so that it's easy to follow the code and track where things are for this we're going to use node and typescript so open up a terminal and just make sure you're in the new folder that you just created in your directory so it should be notes apps and then in here we're going to type npm and net so what this does is it helps us create a new npm module which gives us access to lots of npm packages it gives us a wizard type thing here so for package name just keep the default and for version and description you can keep the default as well now for entry point we're going to have our code and the source folder in an index.ts file so we'll Define that in here and for the rest of these you can just press enter to skip freedom and at the very end it's going to ask us is this okay it's going to give us a preview of our package Json file so just go ahead and hit enter and then that brings us back to our command line so if we look at the package Json file you can see it's got all the stuff we just defined so that's good okay so next we have to add a whole bunch of stuff for our Dev dependencies so we'll start by adding TS node this will give us all the types for node We'll add typescript since we're using typescript We'll add node mon which gives us hot reloading and then we'll just add the types for Cars Express and node and don't forget to see if Dev flag at the end as these are Dev dependencies only and then we'll just let those installed next we need to install the rest of our dependencies so we'll install the Prisma client cores Express and Prisma so Prisma and the Prisma client is used to talk to the database for us without having to write any SQL commands ourself and express is the framework we're going to use to create our API endpoints that'll handle the requests for us and then cores is a security thing that lets us bypass browser cores issues when we're developing locally so we'll just let those install as well that looks good so next what we'll do is we have to initialize typescript in our project we'll do MPX TSC and then dash dash init and then this gives us a TS config Json file you can have a look at this if you want it's got a whole bunch of stuff in it we're just going to use the defaults for this project as they're good enough what we'll do is we'll jump into package Json and we're going to create a new script that lets us start our server what this will do is this is going to use node mon to start our server and watch for any changes anytime we make changes it's automatically going to hot reload for us okay so if that's the footed away next we can create our index file which is going to hold our server and API code So within the notes app server folder we're going to create a source folder and inside the source folder we'll create an index.ts file so in here we'll import Express on course and then we'll create a new Express app and then we'll tell the app to use express.json so this basically helps parse the body from an API request into Json so we don't have to do it manually and then we'll tell to use cores as well and the last thing we need to do is we need to call app.listen so this essentially starts the server on whatever Port that we have defined so we've defined that the port has been 5000 and then we just pass a little function in here after the server starts to log a message which says that the server is running on Google host on our chosen Port this looks good what we can do now is open up our terminal again in and it can just make sure you're in the right folder so it's not app server and then just do npm start so this will call the script that we created you can see it's calling MPX node mod behind the scenes and a bunch of node mon stuff appears and it's pointing to our index.ts file and at the very bottom you can see our console message has appeared so all seems to be working good so next what we'll do is We'll add a little endpoint in here just to make sure that the express stuff is working so to Define an endpoint and express we do app.get and then we pass in the path to our API endpoint so in this case we can say slash API notes so this is what our UI will call to get all the notes eventually and then we pass in a function and the Finesse function we're just going to use the express response object to return some Json and we're just going to pass a message which says success so if we save this and open up a terminal again and keep your server running in this window and you can open a new terminal using the plus icon on the right hand side and then we can use the curl command to to call the endpoint which we just created so it's going to be localhost 5000 which is where our server is running and then our endpoint is on slash API notes so if we hit enter you can see we're getting our Json object back but that's pretty much it in terms of the setup what we'll do next is we'll create a postgres database and connect it from our server okay so next what we need to do is get ourselves postgres database setup so there's a few ways to do this you can set things up locally if you prefer but what we're going to do is use postgres as a service through elephant sql.com so there's a few benefits to this it means that we don't have to set up anything locally and then if you ever decide to host your app online somewhere it means that you'll have a database set up already and it's also quite easy to set this up so if you go to elephant sql.com and click on get a managed database today there's a few options you'll see what we want to do here is select the free tier so this gives us a free database to play with for development go ahead and click on try now for free and then go ahead and sign up so at the top here you'll see a bunch of notifications that says you have to enter card details and all this stuff you don't have to do this unless you have selected one of the paid plans but since we're on the free plan we can ignore this so go ahead and fill in a name for your database that can be whatever you want and then just leave the plan and the tags field as it is and then on the bottom right press select region and here we have to choose a data center it doesn't really matter too much but it's always better to choose a data center that's closest to you so as you can see from a drop down there's a bunch of options so just pick whichever is closest and then on the bottom right click review and there isn't too much to review it's just double check your name on your region and on the bottom right click on create instance and that's it we've created a database so if you go ahead and click on the name of the database you just created using the link it'll bring you to the details so in here you can see a whole bunch of stuff so it's created a user let's create a password and it's created a URL so the URL is the most important thing that we want to have a look at here because this is what we use to connect to our postgres database on elephant SQL from our code okay now we have our database set up and we have a connection string we're going to connect to the database from our backend server so first thing to do is to copy the URL that you'll have on your screen so this is essentially your username and password that connects to the database so make sure to keep it secret and then we'll jump back into the code and within the notes app server folder what we're going to do first is create a new file and it's going to be called dot EnV with this is an environment file so it lets us put properties and config that will change for a given environment for example for development you might have a database that sits an a development environment on your local machine and then in production you might have a different database that you want to point to so we can specify these types of settings in here without having to go in and change any code it also keeps these things secret because you typically don't add and environment files to get so just make sure if you are checking this code into your own GitHub repositories.env file isn't part of the repo once we've created that go ahead and add in the database URL property and paste in the string that you copied from elephant SQL just as it is okay so once we've done that we can use Prisma to connect to our database so we installed Prisma earlier on when we set up our backend server so all we have to do is open Terminal and make sure you're in the notes app server directory and then we'll type MPX Prisma init what this will do is it'll create a Prisma folder and it's going to have a schema.prisma file in it so our terminal has a bunch of instructions you don't have to follow those right now we'll open up schema.prisma and we'll have a look in here so as you can see it's generated to some stuff for us the data source here is probably the most important thing to look at because this is how it connects to the database arm elephant SQL so as you can see it's picked up the provider as being a push SQL database and it's taken the URL from the environment's variables so painting the scenes prism is doing all the heavy lifted to connect to our database and this is essentially it what we have to do now is create a model that's going to represent the note this is effectively going to be a table and our database called note so we'll add in the properties that we know that we want to store for a given note so we'll say ID and then this is going to be an integer and we'll declare it as being an ID and then we'll say Auto increment so this means that the database will handle the ID value for us and then the title is just going to be a string and content will be string as well so that's the outline of our table so we'll open up a terminal again and then we'll type MPX Prisma DB push so what this does is it's going to take our model it's going to create the tables and the database for us automatically and it's also going to give us a Prisma client which we can use within our code to query the database so if we run this you can see that it's doing some stuff and it gives us some messages to say that the database is in sync and it's generated a prism a client once we've done that we can jump back into our index.ts file where we have our endpoints and what we need to do is create a new Prisma client so this is the thing that was just generated for us so go ahead and add your import statement to the top as well and then down in our app dot get endpoint what we want to do now is use Prisma to pull some data from the database to do this we use the Prisma client and then we say dot note so the dot node references the model that we just created and then the find many is going to return everything within that model in other words what this is doing is essentially going to the note table getting all the rows and returning the data to us after we've done that we'll assign it to the notes variable and then we'll just return this notes variable as Json so our database doesn't have any data in it yet we've just created a table so what we can do is go into elephant SQL on the browser and on the left hand side there's a browser tab if you go ahead and click on this you can see it brings up an SQL query thing and if we click on table queries we can see we have the note table in there and it says no rows so this is good as it means that the Prisma client worked to generate the tables for US based on our model so we've proved out that our backend can talk to our database at least next we'll just run an insert statement to add a row to our note table so we'll run an insert statement and then we'll just add a title and then we'll add some content so we don't have to specify the ID field in here because the database will handle that for us and then on the bottom right click execute and all being well it should give us some data so if you click on table queries again and if you select the node table it'll add and select create your input and then go ahead and click execute and it should hopefully have a row in here with whatever title and content you added so the this is a quick way to get data into your database for testing and if we jump back into the code we can open a terminal again and we'll start our server if you haven't started it already and then we'll open a new window and here what we'll do is just curl our endpoint again and all being well you should see an array of the notes that we just created so using curl is good for testing apis quickly but it makes it harder to build out more complex requests for example whenever we're doing post requests we'll often send a body and headers and things like that so what we'll do now before we create the rest of our endpoints is we'll install a client which helps us make API requests a lot easier so there's a few things out there like Postman that you can use but we're going to install thunderclient on vs code which makes it easy to make requests from profender IDE so if you go to extensions and type ThunderClan you'll see it appears on the list of extensions so it's got a purple logo and if you install that after you have done this you will see the Thunder Clan option on the left hand side in your taskbar so if you click on Thunder client it'll bring up your list of activities so this is going to be the past request you've made if you go ahead and click the new request button at the top you can see it opens a tab within Visual Studio in the terminal just make sure your server is running and then what we're going to do is test our get endpoint just to get a field for how to make requests using ThunderClan so in the URL bar here what we're going to type is the address of our notes endpoint and it's going to be a get request so if we click send you can see in the little window here that we've got a response and the status is 200 and you can see we've got an array that contains our note this is what we'll use going forward to test the create update and delete requests you don't have to use this if you don't want to so use whatever you feel most comfortable with okay so next what we'll do is We'll add the endpoint that lets us create a note so in index.ts just below our get endpoint code we'll use the app.post function to create this endpoint to the structure is similar to the get endpoint just this time we're calling app.post and again we pass in pass in the URL where we want the post endpoint to be on and then we pass in our function and our function the first thing we'll do is we'll get the title and the content from the request body this is what the UI will send us whenever the user fills out and submits the add note form once we have that we can call the Prisma client which we created earlier use the create function that exists on the Note model to create a new note so we'll pass in the title and the content which we got from the request body so the prismac client will return a new node to us with an ID a title and a content and assign it to the note variable we will just return this as Json back in the response so if we go into our ThunderClan Tab and if we change the method from get to post so we can keep the URL the same this time we need to add a body so if you click on the body Tab and it's going to default to Json which is what we want so in here we're just going to pretend like the UI has sent the back end and add note request and it's going to have a title and it's going to have some content so it doesn't matter what these values are and then if we hit send you can see in response at the bottom here that we have a 200 okay which are Express app sent along with the response so you can see that we have an ID this time so this is the ID of the note that was created whenever we saved it to the database and then we have a title and content as well so it's good to return the entity did you create back with the response as it means the UI can use these things for whatever it needs to do okay so we want to add some validation and error handling in here just so our code doesn't break if things go wrong it's packet index.ts what we want to do is say if the title or the content fields are empty we want to return an early response of 400 which means bad request and then we'll just send a message as well that says that both of these fields are required so we can test this out by going back into our thunderclient Tab and if we change the request body to remove the title or the content and if we hit send you can see this time we got back 400 bad requests status in the body of the response we got back our error message next we want to catch any errors at the Prisma client throws us to do this we'll use a try catch and then we'll just copy and paste the code that we added before into the try part and then in the catch we're just going to do similar to what we did before and say if we have any errors then we're just going to return the 500 status and then send a message as well so this is in case there's an error connecting to our database or anything else that could possibly go wrong when trying to save to a database so we're just catching that and handling it properly if we don't do this it could cause the back end to crash okay so now that our post endpoints in place and we have a bit of validation and we have tested creating a node using it we should be able to do a get request to the same Point again and it should return us two notes the first note being then we added manually to the database and the second note being the note that we just created through ThunderClan so we can try this by changing from a post to a get again on the same endpoint and if we hit send we should have two items in our response and we do okay so next we'll add the endpoint to update a note so just below the code where we added app.post we'll do app.pit and then we'll pass in the URL of our put endpoint and again this is similar to what we did with our previous endpoints the only difference here is that we specify the ID using a colon this acts as a placeholder so when we make a request to update a note the endpoint will be slash API slash notes slash and then the ID of the note that we want to update and just like before what we'll do in here is we'll capture the title and the content that we get from the request body and we'll also get the ID from the query params we also want to convert this to an end as our IDs are stored as integers in the database and we'll just add some validation in here for the ID to say if if we don't have an ID or if the ID is not a number then we want to return an early response that says 400 status code and a message that says ID must be a valid number next we'll add a try catch and in the try section we will use the update function that exists on the Note object to update the Note for the given ID so what we can do in here is we can add a where object which is essentially a where clause and SQL we'll pass in the ID here as we want to update the Note for a given ID and then we'll pass in the data that we want to save so the title and the content get from the request body as usual we will return the updated note in the response and in our catch block we will say return status 500 and just send a generic message if something goes wrong trying to save to the the database so we can test this now by jumping into our Thunder client Tab and we'll update the Note which has an ID of three so it currently has test title and the content is test content black so we'll change these two Fields we'll change our method to be a put and we'll send the title and the content as a Json body and we'll just make a change to the title just to make it obvious that we've changed this note and in the URL we want to pass in the ID of the note that we're changing so in this case it's going to be ID3 and if we hit send you can see we get a 200 status and if we look at the note that was returned to us which was also saved to the database you can see the title and the content match what we just sent along with the put request now if we make a get request to our notes endpoint we should see that the note is up is also updated there as well so ID3 and it has our our updated stuff so last thing to do is check our validation for this so if we pass in a random string that isn't a number then we should get an error saying that this is not a number and we do we should also add some validation in here for if the title or the content fields are empty as these are required in the database so if we go back into our app.pit function and index.ts and we'll just add the code somewhere to what we added to the post request where if the title or the content our empty then we'll return a 400 status and we'll send an error message so now all that's left to do is add the delete endpoint so just after the code for the put endpoint We'll add the delete endpoint so we'll say app.delete and again this is going to be similar to the update endpoint where we accept an ID as part of the query param and in here we'll just check that the ID is a valid number and if not then we'll send back our 400 error code and we'll send an error message along with it if we get this far it means we have a valid ID so we can go ahead and open our AI catch block and we will use a delete function as part of the note object on the prismac client to delete the note where the ID equals the ID that we received as part of the query params and instead of returning a note object this time we're going to return a 204 status which means no con this is an ideal way to tell the UI and other consumers of our API that when they delete entity that it was successful and in our catch block we'll just add the usual stuff we'll send a 500 status and a generic error message if we get an error when we try to delete from the database and our request tab what we can do now is change the method to delete and then we'll just delete the note of an ID of three and if we send this you can see we get a status back of 204 no content and if we do a get request to our notes endpoint you can see that the note with an ID of 3 has been deleted okay so now we've got uh our back end in place and we have our UI in place what we need to do is we need to connect the two together so we'll jump back into our front end the layers will take a new line just underneath our state objects at the top of the component and then we're going to add the use effect hook and here we will create an async function that calls the API so we have to put this in a separate function because react doesn't like if they use effect itself as async it just doesn't work within this we will have a try catch block so we use a try catch block to handle any errors that might come back from the apis our try block will have the logic to call the API as we will see in a second and then we'll just catch all the errors this prevents the app from breaking if there's something wrong with the API request or if something happens that we're not expecting so inside the try part of our try catch what we're going to do is we're going to use the built-in batch function in to color API remember our API is on Bluetooth 5000 slash API slash notes and by default the fetch will do a get request so this is all we need to do to make the request once we've made the request what we need to do is we need to take the response and convert it to Json so remember our endpoints are going to give us back an array of notes depending on the action we're doing so in this case we're doing a get so we'll get an array of notes back from our back end we have to assign this to a variable which we'll call notes and we'll give it a type of note array and then we'll just call a width response Json so this will convert it to Json for us and if all goes well at this point then all we have to do is update the state with all the notes that we just got from the API so we'll call the set notes the object function and we'll pass in the notes and in our catch block all we'll do is we'll just log any errors that we get so we've created a function but as you see and it's not being called yet so what we need to do just at the bottom of the use effect Hook is we need to invoke this function by calling it using brackets and the last thing we need to do is we need to add our dependency array and here the last thing we need to do is add our dependency array in here so just outside at the last curly brace we want to add a comma and then add an empty array so this code will only run the first time the app renders now if we save you can see on the right hand side in the browser that the note that we have on our database is displayed so if you've been adding your own notes or deleting notes through the database then whatever you've added to the database should appear here as well once that's done what we can do now is we can delete the array that we added to our notes State value because we don't need it anymore this was just the data that we had hard coded to help us build out the UI so you can go ahead and delete this and just add in an empty array but this means is that the note state will be empty initially then the user factor is going to run it's going to get all the notes from the API and it's going to update the state so next we're going to look at how to save a note to our backend so if we jump down to our handle add note function we have some logic in here that adds a note to the UI so what we'll do is we'll delete the the new note object which we create on the front end because our back end is going to give us back the note with all these properties once it's been saved to do the database so we can delete this and just like before We'll add a try catch where we will add our API logic and we're just going to copy and paste the state function calls that we currently have and put it inside of the try section because we'll need this stuff after the API has completed the request so we'll take a few lines at the top of the try and what we'll do here is we'll call the API similar to what we did with the get but this time we have to pass in a second parameter to the fetch function and this is going to be specify some properties that we need to make a post request so in here the first thing we'll do is We'll add the method and then we'll add the body that's going to contain the title and the content that the user entered into the form we use Json stringify here to convert it into my Json string and since we are making an API request make sure to add the word async to the function after that we're going to get the new note back in response so just like before we'll take the response and we'll convert it to Json and we'll call this new note and since we already have the logic in place to update the UI it should all just work and the catch block will just log the error we also need to add the headers to our request so just after the method property add a comma after post and add in the headers objects we have to specify that the data that we're sending is of application Json so we do this by specifying a content type and if we save this and open it in the browser and if we just add a new node using the form that we have and if we click add note you can see that it appears in the list so to update a note we'll take a similar approach we will jump down to our handle update node function and the first thing we want to do is we want to add the async keyword to the function declaration because we are going to be making API requests once we've done that we will delete the object which we create on the uid update a node as the API is going to give us back the updated note with all this stuff within it similar to before We'll add a try catch just so we can catch any API errors and handle them in the catch block as opposed to having the app crash and what we'll do next is we'll copy the existing code that we have that updates the UI and we will paste it into the try block okay so now we have an error saying that our updated note isn't defined that's okay because we're going to get this from the API if we take a few lanes at the top of the try block and then we will just add the logic to call the API this will be similar to what we had in the add note logic so the only real difference here is that we are using a template string to define the URL as our pit API endpoint requires the ID of the note that we are updating so we want to dynamically add this based on the selected node that the user has clicked on and the only other change in here is the method so we're saying put because we want to update the Note once we've done that we want to take the response and convert it to Json as this is going to have the updated note in it and then we'll assign it to the updated note variable once we've done this we've cleared the error and the rest of the logic on the UI is the same as before and then the last thing we'll do is we'll just log any error to the console and now if we try this in the browser after we save if we select a note and update the title and update the content field and hit save you can see that the node gets updated and our form clears and then if you refresh the page this data should be persisted so the last thing we need to do to finish off our little app is to add the API call to the delete endpoint so we'll scroll to the delete note event handler that gets called when the user clicks on the little delete button for a given note just like before what we'll do is We'll add the async keyword to the function declaration and down in the body of our function we will add a try catch that will handle our API call and catch any errors and what we'll do now is we'll copy the existing logic to update the UI and paste it into the try block and we'll add the logic that calls the delete endpoint the URL that we enter is going to be a template string so that we can attach the note ID of the note that we want to delete as this is required whenever we call the delete endpoint remember that whenever the user clicks on the delete button for a given note we pass the ID of that note to our delete note function this is where this note ID comes from and then we'll just add our options to our fetch request to say that this is going to be a delete method we don't have to assign the response to a variable in this case because we're not getting anything back if we go ahead and save this and if we try it in the browser if we click on that delete button for a given note and if we refresh the page you can see that the UI updates and the notes being deleted
Info
Channel: Chris Blakely
Views: 17,176
Rating: undefined out of 5
Keywords: Full Stack React Node Project, React, Node, JavaScript, Web Development, Coding Tutorial, Notes App, Build from Scratch, CRUD Operations, React Hooks, Node.js, Express.js, CSS, Bootstrap, Frontend Development, Backend Development, API Integration, App Deployment, Full Stack Development, Project Building, Application Development, Web Application, Programming, Coding Project, Learning Code, Full Stack Tutorial, React Tutorial, Node Tutorial, JavaScript Project, Database Integration
Id: 2MoSzSlAuNk
Channel Id: undefined
Length: 58min 57sec (3537 seconds)
Published: Wed Sep 27 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.