Code Refactoring in React, Node.js, Express, MongoDB | MERN Stack Project

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
no mernstack project is complete without reviewing and refactoring both front-end and back-end code where needed [Music] hello and welcome i'm dave today we will review and refactor our mern stack project code i'll provide links to example source code and all resources in the description below today's lesson will have two code repositories one for the front end and one for the back end of our mernstack project our starter code for the back end is the completed source code from lesson 8 which is the last time we worked on the backend rest api i've got the package json open for our back-end code now and i'm just going to change lesson 8 to lesson 12 and then i'm going to put a dash and put be for back end because we're also going to have a repository for the front end when creating projects i don't get a traditional code review like i would working on a team but the nice thing is as i release lesson by lesson and build a playlist on youtube or wherever you've watched the video i get feedback and questions and i'm able to answer those questions give responses look up details and sometimes viewers catch things that i may have overlooked or they think about things in a different way that's actually one of the things i love about teaching is because i learn as i teach as well my students at university or just viewers on youtube help me see things in a different way so i've had some questions as i've built this playlist for our mirn stack project and they've identified some things and a code review and building in public can of course make you go i am not perfect and i know i'm not perfect and there are some things we need to correct today so thank you in advance well i say in advance thank you for previously reviewing those things and thank you in advance for anything you help me with in the future i do sincerely appreciate it now what we're going to look at first are the controllers and that's when i really started to get some comments when we were building the logic for the controllers specifically the notes controller and the users controller so let's look at this notes controller first and what we'll look for is the duplicates area so we can do control f and we can just search for duplicates for when i was searching for duplicates and well i guess not with an s but just duplicate and there we can find it in the file you could also just go to the controller directory here and then right click and choose find in folder and then you can just search duplicate and it will find everywhere we looked for a duplicate in these controllers and then we could bring that up and that's a good way to do that now the first thing i actually want to do is go to the model because i was asked instead of looking for a duplicate title for example or in the user we were doing usernames why not just set that to unique well unique does help but it creates an index and that will provide a duplicate key error when we attempt to save a record that would need to catch a duplicate but we're not sending you know that user friendly error like we have in the controllers when i look back here let's find the user area here and we're sending specific messages and status numbers for these error messages and so we were getting some granular control some specific control over that and we would have to do that in a different way if we based that say on setting that unique or some of the other things we might do where we would only catch the error when we attempted to save the new user for example and we find that here as we go oh here's created this was actually user.create but other places where we update i believe we save as i scroll down here and look yep await user.save in the update that we see here so we would be catching the errors there in a try catch block if you remember in the controllers we used an async handler and so that catches those errors instead of using a try catch for the await and if we're not expecting the errors the ones that we did not already anticipate that we're grabbing and sending the specific errors that we defined and of course those user friendly messages then they get kicked out to our error handler middleware that we created in the middleware directory here and then it sends whatever the error is that's generated not always quite as user friendly so that's why i took this approach i wanted to handle all of the errors that we could that we expected that we knew we might get and send the specific error messages and status http status numbers like 400 here for example or we'd have a 409 for conflict i believe when we have a duplicate yep there we have that and i wanted to send those specifically and have control over that so that answers some of that like why we didn't specifically use unique but another reason is unique doesn't necessarily check for case sensitivity and that's the second thing i need to bring up that i got called out on and it's correct i'm busted on that one i should have checked for case insensitivity and i didn't so in other words if we put in a name like capital d at the beginning of dave for a username and then we put in dave all lower case they would be different unique wouldn't catch that and we would allow two daves to have that username so we want to make that search case insensitive in other words instead of case sensitive now i'm currently in the users controller i can highlight that here in the file tree so let's make the change here first that will adjust our search and make it case insensitive and i've received several suggestions on how to do this also as far as just setting everything to lower case or requiring that on the input but then of course our users would have to say they just want lower case and we wanted to go ahead and allow uppercase letters or i wanted to for this project so i didn't do that a regex was also suggested and you could set the case in sensitivity on the regex that would be another good solution however there is a solution that is documented for mongodb and the mongoose js documentation links directly to mongodb for that and it will easily adjust this for us so all we need to do is find our initial search for that duplicate so let's go ahead and search for duplicate in this file once again and we can see we found five of nine so it's in at least a couple of places here's the first area right here so let's see what we're in we're in the create new user handler here inside of our users controller and we're just going to change our find one that we have looking for this duplicate right now it says await user.find1 we pass in the username we have lien because we don't need to get the entire object back we're just checking that username then we execute that but what we can do is use a collation and then you just have to add what strength you are providing for the search and we can chain it right in here i'm going to press alt z so this wraps so now you can see we have the find one and the username and then i've added this collation and i will link to the documentation in the description for this but you must provide the locale property here and after that you can set a strength and we'll just go ahead and set that to two and there's several things that that does one of the things that it does is it checks for that case insensitivity so simply by chaining this to our find one request and then of course having lean and exec after this will fix our problem and it will check all capital letters or all lower case letters it doesn't matter two daves will still be identified and only one person will be able to have the username dave no matter the capitalization or the lower case so let's go ahead and find the other instance that we're looking for a duplicate in this file and let's apply the same there and here we are on line 72 now let's see what we're in this is in the update user once again we're looking for a duplicate here so we want to put that right after the find one i'll just paste that collation in and that will work okay now let's go to the notes controller and make this same adjustment for where we look for duplicates there and let's make sure we're on the first instance of duplicate there we are so we have note find one and we can put the collation it's the identical code there's nothing that changes here that's different than where we put it in the user controller it's just a collation with the locale property i'm setting it to en for english and you could set yours differently if you want to and then we have strength and it's set to 2. and after we find that one let's go ahead and find the next time we use duplicate and it's here probably inside of the update note just like we had update user and we'll put that here as well and save okay another review comment that i had was we have a default in the user model and that default has employee set here and we have a string for the array now it said the comment i received and they're correct that if we provide this default we don't really need to require a default role to be sent or the role's value to be sent at all when we create a user and i remember going through that tutorial and i said i'm going to require the roles anyway but it doesn't hurt a thing but we can fix that so the default is available however i believe in our front end code we've already required the roles so it's not a big deal but i did just want to show how to do that and i also wanted to fix something here in the schema as i went over that and this is worth noting because we actually put this in differently than it should be and i just didn't catch it before so this is good to note right here what we want to have instead of having the array here around everything we'll put roles have an object then we'll say type string and we'll just put the word string inside of this array right here after that we'll have a default and we'll also put the default value inside that array like you see there okay now that we've made this change to our user schema and i'm going to save this file let's go back to the users controller and let's find the create new user method once again i'm scrolling up here we are on line 24 in the user's controller for create new user so we can just make a couple of changes here that will not require the roles but we'll still use them if they are received like we are getting here from the request body so here's where we were requiring those and saying all fields are required well we can change this then if we're not going to require the roles to be received and just remove this last part of the conditional so now we're just checking to make sure we've received a username and a password after that let's just scroll down to where we create our user object and now there just needs to be a little bit of conditional logic right here instead of always sending the username past the hashed password and the roles as we create a user so i'm going to change this and we're going to use a ternary statement and i'll just put this in and save so you can see the better formatting and here we're creating the user object and we're providing a conditional here basically the same conditionals that we took out up above and now we're saying if these are true if one or the other then we're going to do this where we just send the username and the hash password so this means if we do not have an array of roles or if we have an array but it doesn't have any length essentially nothing's in it then we're just going to use the username and hash password otherwise we're going to do what we were doing before send the username the hash password and the roles as we create the user so that easily makes the change for the comment i received on that and of course like i said you don't have to because in our front end code we were definitely requiring the roles but this just makes it a little more thorough and shows yes that can be done i did also receive a couple of comments about why i was choosing for instance save instead of using say find one and update or find one and delete where i was just using say find by id or find one and then later on actually saving the changes as we see here in the update user and i've got a couple of reasons to explain that one is again i wanted that granular control or more control you could say to give those specific error messages where as if i was using the find one and update essentially we'd be trying to do everything at first i wouldn't be checking any of this beforehand and then i would be handling errors afterwards and that brings me to my second reason then i would have to use a try catch block instead of using the async handler that we had before that would kick those errors out to our error handler middleware immediately using the try catch we would have to handle those errors afterwards and of course we could give different reasons inside of the catch and then we'd have to pass the error to next so it could be done it's just a different way of doing it also i guess a third reason here is when i teach things i tend to do one step after the other not so declarative and sometimes when i'm just coding for myself i may be a little bit more declarative but it's easier for me to walk students through steps one by one so that is another good reason that i didn't just try to do everything at once so we walked through each step here everything that i would look for in a controller each error message that i would send back and eventually we save our changes and of course send a successful message and just one final note for our back end code and this will impact the controllers and it's our use of async handler we're bringing this into each controller we're wrapping our methods that have async a weight and of course if there is an unexpected message because this async handler lets us avoid using try catch blocks but if there is an error that we didn't expect of course like here's the 400 we are expecting that says no users found but if there's something we didn't expect and it gets kicked out then it goes to our error handler but there is another package i have discovered that is actually easier to implement than this async handler it doesn't require us to wrap every method but it is easily applied by just requiring the package in your server.js so you don't have to make this change our async handler is doing the exact same thing i would just recommend it for the future because it's easier to use if you do want to implement it we will need to remove the async handler and anytime we wrapped it around a method inside of our code so i won't walk through doing each one of those but i will show you how to install the new package and what the name of that package is so let's go to the package json i'll scroll up here so we can see our dependencies and then i'm going to control backtick and then i'm going to say npm i and then it is express i could spell express dash async dash errors instead of handler i'm going to go ahead and install this and then all we need to do is require it at the top of our server js so i'm going to close the terminal so we can see just a little bit better and i want to put it before the port but after that it's fine so we could just require it right here and as long as it's required and i guess because we're doing the same with dot env instead of having it right here i'll just put it at the top underneath the dot enb require and then it just applies itself everywhere in your application so you do not need to do what we did with the async handler that you see being imported into each one of the controllers and then wrapped around each method so i'm going to remove those you and then i'll come back to the code you can do the same if you want to or for this project if you want you can just leave your async handler in there i'm also going to uninstall the express async handler and i guess i could do that now to show you in the package json as well so that would be npm uninstall and then you just name the package so express async handler again only make this change if you want to okay i have removed all the instances of express async handler from my controllers i'll just show you one for example no import at the top of the auth controller now previously the login method had the async handler wrapped around it and i have removed that as well and i've done that for all of the different methods in each of the controllers that we're using the async handler so no import and no wrapping the async handler around any method if you're using the package express async errors now and again the only thing you need to do to use express async errors is it required at the top of your server.js so yes a nice change to a different dependency if you want to make that change one more change to our back end code and then we'll be finished and able to move on to the front end repository but this change is going to be inside of our middleware and in our error handler and this is something we need to do because of how we're handling errors in redux and rtk query right now if an error gets kicked to our error handler it sends the message and that's pretty much it so we don't know what the status is going to be it's kind of a mystery status and we figure it out along the way and if we don't know it we set it to 500 which is a server error but what we do need to do is one extra flag that rtk query is going to look for and that is to be is error is true now the other errors that might be encountered rtk query will already know their errors but we want these messages from our error handler to specifically be flagged as errors and we'll be able to handle this as we validate the status back in our api slices in the front end code so this is just something we would need to communicate to the back end developers if you were working on a team that hey we're using redux with rtk query and any unexpected error it would be nice if you could set is error to true for us so i'll go ahead and save that and with that final change we're finished with the changes to the back end code so now let's move on to the front end repository now we're at the starter code for our front end repository and the last time we worked on the front end was just in the previous lesson lesson 11 let's just go ahead and change this to lesson 12 in the package json and save our file now from there the first thing we need to discuss is what is in the notes and the users api slice unfortunately we have a few more changes to make to the front end so we better get started quickly and we'll go to the features directory and let's go to the notes and now we can scroll down to the notes api slice now something that i overlooked that a viewer kindly pointed out to me was the validate status i put in here i put it outside of the query and it hasn't heard anything our app has been functioning however it's actually a property that belongs to the query right now i'm just giving the query the notes endpoint here the address to attach to the base url we need to change this and apply the validate status and then we'll identify notes here with a url key so let's go ahead and highlight this full query right here under get notes you can see when i paste this in now it's going to look just a little different now we have a parentheses and an object and here we say this is the url and there's notes and now we have our validate status here now coming just from the back end code where we made that other change if we have an unexpected error we're not sure what the response is going to be then it goes through this validate status process and notice we say if we do not have result dot is error and that's specifically why we were setting that is error to true in the error handler middleware in the back end so it would catch right here which will allow us to display the error message that we get something else worth noting while we're in here is that if you've got an error about response.data and map not being a function well that means you do not have an array at this point that response data has to be an array to map over it so you could check to see if you have an array here and do an early return i'm not going to put that in because i'm going to say look you need to know what errors you're receiving and of course this validate status helps with an error that you might not expect as well so if it's not coming from your error handler or it's an unexpected error well then you just need to have control of that data and you should always be receiving an array here so you could put in a check for an array but you're going to have other problems right afterwards with the provides tags as well for example and you really just need to have an array at this point so make sure that back end is sending the expected response and if it's not the expected response it should be an error okay let's save these changes to the notes api slice and let's do the same to the users api slice because i made that same validate status mistake right here where i had it outside of the query so i'm going to go ahead and adjust that and now we have our users url and the validate status is part of the query object okay now i'm going to close these files but we're going to go up and look at our pre-fetch component that is inside of the auth directory now this has definitely been working for us i'll press ctrl b so we can see it a little easier here and what it's been doing is initiating the state for redux and so it's made sure that these queries have all of their data at a time and of course we can even refresh the page and it grabs that data again quickly but it is using the initiate we need to break away from the actual redux that we're used to using because then when i pull in this data later say in the note component or in the edit note component for example we're using the use selector and then we're passing in a selector but what we really need to do is use the rtk query use get notes query that also runs and then of course we can select results from that we don't have to request that data again and we can use this prefetch component to instead of putting that initial state with initiate into redux we can use it to actually pre-fetch and it makes it just a little bit easier actually so let's go ahead and do that i'm going to remove the console logs as well and i'm just going to paste in what we do and i'll save this so it comes over but what we do to actually use a prefetch that is built in and we can pre-fetch those hooks that we are using so we have the notes api slice dot util dot prefetch and then we identify the end point and we have a get notes endpoint and a get user's endpoint now let's go ahead and pass in an argument to name these just like we did in the hooks query notes list and users list and of course then they will be the same subscriptions and that subscription is what a component does it says hey i'm using this data to redux and so it is subscribed while the component is mounted after it unmounts it holds the data by default for 60 seconds but we've shortened that up in our slice by saying keep unused data for only five seconds i'm also passing this force true here so that means anytime it comes to the prefetch even if it has that previous data it's going to query it so that just forces that query even if the data already exists in there we can also just remove this return there's nothing to unsubscribe from here this is just a pre-fetch so i'll remove that return so we don't have to clean up that is the cleanup function of use effect and we can pretty much get rid of the empty spaces if we want to as well i guess i could bring use effect down one so it's a little easier to see from the prefetch but there we have changed our component now this is going to break a few things right now so we'll need to change those as well and we'll see those in those children components from our list right now we'll just be pre-fetching those hooks that we have in the users list and the notes list i'm going to show the file tree again and let's go to the package json because as we go through some of these child components like the edit note and the edit user i want to add a spinner as well so let's just go ahead and add that dependency and as we're editing those different components we can add the spinner in also so control back tick to open up the terminal and npm i and then react dash spinners and this is a nice package that provides some pre-defined some already created essentially spinners that we can apply inside of our project and so now we see react spinners has been added as a dependency now let's go to our note component and what we need to do is actually use the data we already get from our notes list query right here we have use get notes query inside of our notes list but then when we pass it to note what we've currently been doing is using the use selector and passing in a selector well we're changing this approach now so we won't have the use selector or select note by id so let's go ahead and remove those and then in its place let's go ahead and import our use get notes query that we're using inside of our list as well but we're not going to have to query all that data again because what we can do to define note instead of this use selector and i'll delete that and just paste in the difference and we'll look at how this works we can define our note from the use get notes query that we have in the notes list and we're naming it the same but then it has this function called select from result so we already know we have a result and we're getting the data from that now remember we have our data broken into an ids array and then entities and what we want is the specific notes so we're passing in the note id and then here we're just defining the note when we select from result this is a selector essentially for our use get notes query data and here we have data dot entities and then we're providing the note id and that gives us the note in the same way there's no other changes to be made here we're just getting that data in a different way so we'll save this and now we should still be able to have all of these notes and we're only making the one query with use get notes query this will not create a separate query or network request i should say it will get this note from the data that is already queried and while we're in the note component there's one other optimization we can make so let's go ahead and add it as well we'll say import and this is going to be memo and it comes from react you may have heard this referred to as react dot memo where we would just import react and then use dot notation to use memo but we can just destructure memo this way as well now at the bottom of this component then we need to go ahead and put that in place and i'm going to say const memolized note and then set that equal to memo and then pass in the note we have created we'll create some space here as well and then instead of default here for the export default note we will go ahead and export the memoized note now this component will only re-render if there are changes in the data now let's do the same to our user component so we are no longer using the use selector or select user by id and instead i will import use get users query and then from that we can get rid of where we're currently defining the user with the use selector and instead i'll paste in once again our use get users query we select from result and we get the data and then we get the user that we need after that we can also import memo here and let's get that from react there in our list there we go and then we can scroll to the bottom and i'll create an extra line here and i'm going to define const memoized user set this equal to memo pass in the user and then our default export will be the memoized user here and i should add if you're not familiar with how react memo works i do have a separate tutorial on that that i'll link to in the description as well now let's move on to our edit user component and we have a few changes we can make here at the top i've got the imports we need so i'll put in the use get users query once again and then i'm also going to import a pulse loader from that react spinners package that we added as a dependency and you can see it has react dash spinners slash pulse loader which is one of the choices and i'll put a link to that full package in the description also you might want to make a different choice than the pulse loader that's what i'm going to use i'll get rid of that space and we can once again define our user inside of this component and it's going to be just a little bit different because notice we have an id now that we're passing instead of an id that comes in here we're getting it from the params which would be in the url and so then we can use that select from result and we pass the id here instead of being destructured as a prop it comes from the use params and either way we still end up with the user and now i'll scroll up just a little bit and i'm going to change some of this logic that we have here no longer going to use the ternary i'm going to say if we do not have a user we're just going to return that pulse loader that means it is probably still loading if not we're going to of course create the content and then return that content now let's move on to the new note component in the notes directory and we'll once again import what we need at the top this is the use get users query notice that even though we're in the new note we're pulling in the users because we need those users when we create a note to assign the note to a user and once again we're going to replace the use selector and the select all users selector and we'll put in our select from result using the use get users query here now that means we do not need these imports i should go back and check that of course in the last component we're in i may have forgotten to remove the old imports but after we define the users i'm going to change one other line here and that's because we're going to use that pulse loader again so instead of saying not currently available we'll put the loader here if the users do not have length and then of course have the content equal to the new note form and return the content let's quickly go back and see if i have some old imports at the top and i do we don't need the use selector or select user id here inside of the edit user component how about the user component it's fine and the note component looks like it's fine too so we're good there and now let's move to the edit note component now i had a separate question on this component that i received and it said hey we could use one more layer of security other than what i put in in the last lesson which was about role-based access control and permissions and this would be what if an employee tried to edit a note that isn't available to them through a role just by changing the note id in the url now you'd like to think your employees aren't malicious and that it might even be hard for them to get whatever note id would exist that they would want however we can go ahead and programmatically correct that or look for that so let's go ahead and do that while we're here so i'm going to add a few imports at the top we'll notice we've got four imports here we've got the use get notes query and the use get users query we're also going to bring in our use auth hook and then that pulse loader that we're going to use and we can get rid of the selector select note by id and select all users and we can also get rid of use selectors so let's delete all of those and now let's go ahead and put this code into place i'll just start by replacing how we're defining the note and users here and paste in the d structure from our use off hook and then also how we define the note and i'll save that but we still need to handle the users so now i'll put that underneath and let's look at the information that we're getting here we'll quickly break it down in case anything is different so we're bringing in the username is manager and is admin of course we're using that use auth hook to make sure for that situation that i described where an employee could still possibly enter a note id in the url and get access even though their role didn't permit them so we're going to prevent that from happening here we're getting the note and we're getting that id from use params once again to define the note now when we get the users list we're doing this a little bit differently and we should have done that in the last component too for new notes and that is we're mapping over that data the ids array that we get back that is iterable the entities are not so we need to map over the ids array for each id we're grabbing the entity which is the user and putting it in a new array and so users ends up being a user's array for us here and if we look back at new note that is the same thing we did here which i didn't review quite as thoroughly but it's the identical thing we end up with a user's array so we can save those changes and now we're going to change this content line here so i'll highlight this and put in a few changes again this is somewhat to prevent that possibility of an employee entering in a note id into the url and still gaining access to it even though their role didn't permit them but the first thing we're doing is making sure we have a note and that we have a user's array with some values in it and we're returning the pulse loader if we don't so we may briefly see that while we're waiting on this data after that we're checking to see if we do not have a manager or we do not have an admin and if we don't have either one of these we're just going to pass along this second conditional here which we could chain but then we'd have to put this twice like is manager and this and then is admin and this and by nesting this we just have to do this once so we're checking to see if we have an admin or manager and if we don't then we're checking to see if the note's username matches the current username that we get from use auth now if they don't match then we return no access so that solves our problem other than that we define the content and return the content here okay so we've made some big changes into how we get the data now we're not pre-populating redux and that is going to let our queries use the data that we get from the use get users query and use get notes query in the lists to be reused in the child components and that works out just a little bit better it's also going to allow us to see updates from other users and that's very important i'm back in the backend code now in a separate instance of vs code i'm going to start the back end rest api first with npm run dev once we confirm it's running then i'll go back to the front end code and i'm going to once again open up a terminal window and there i'll type npm start to start the react app and we should see it open in our chrome browser okay our app is up and running i'm going to open up chrome dev tools and i've got the network tab open so let's log in as our stakeholder dan d and this network tab is going to let us see the requests that are going out so we're at the welcome page and now we have a request to the auth endpoint to the notes in point and to the user's endpoint so we have pre-fetched that data now if we go to view the tech notes another request went from our query to notes and that's okay so we have that data now let's go ahead and look at an individual note and notice no extra query went out we're using the data that we already got from our use get notes query so that is what we wanted to happen and now i had an access token time out and so it hit the refresh endpoint and we've got another notes query here but that is due to how the timing is set currently in our backend code which of course before we deploy we want to make sure we're at 15 minutes and seven days 15 minutes on the access token seven days on that so i'll want to change that i think from lesson eight we had it shorter okay now let's go to the users and we can see we have a user's request here by the way notes is still has a polling interval of every 15 seconds it's going to request notes again but we've got the users and now if i go to an individual user like our test user it didn't put in another request to users either so that is also working as we wanted it to so that's great now let's go back to our user notice i've got a user here named dave that's an employee let's try to create a new employee and we'll just name him dave all uppercase and i'll just put in a simple password and let's see if we can save and note now we get duplicate username and that's because the collation we put in our backend code is checking for that case insensitivity so even a lowercase dave will match in all uppercase dave so that's also what we want i'm going to quickly bring up the back end code once again let's go to that auth controller and i'll check the timing that we've currently got set here from lesson eight yep 15 seconds on the access controller we want something a little longer than that so i'm going to go to 15 minutes and i'll probably need to scroll down to find the second place that is set yes 15 minutes instead of seconds it looks like we were already at seven days for the refresh token those are the numbers we want to use in for this project so now that we've set that that should change things a little bit i'll clear that out we'll log out notice on the log out we had notes because it refocused on the window and we've got a refetch on focus but after that we hit that log out in point it deleted our secure cookie with the refresh token when we logged out now let's log in again and check out some state in redux dev tools so i'll log in with dandy first and once we're logged in i'll open up our dev tools window and now let's go to redux and i'll pull this over so we can see the state a little bit better on the right and let's look at this api state and we currently have our queries that are identified as notes list and users list and then we also have subscriptions and we can see the subscriptions here as notes list and users list and of course it lists the end points beside those as well now if we break this down we have two subscriptions here it looks like and two here under get users see what happens when we go to tech notes and it adds some more so now this is one for each of these notes that it created and that's okay too because we're using the use get notes query there but we're not creating another network request as we saw before when we look here we've just got notes and then once again notes there and we could log out and see all of that happen one more time so we'll go dandy login and so now we went auth notes users we go to notes we'll see another notes request but now we look at one of these and we don't see another notes request there so requests network requests are not the same as redux subscriptions and that's important to point out but subscriptions last as long as a component is mounted and remember each one of these notes in the list is a note component that is mounted as well so now instead of looking at our state here let's go ahead and look at the profiler too now we can record some data as we profile so let's go ahead and make a change to mrs smith's computer problem although it says it's completed we can go ahead and just maybe add another exclamation mark here to the end and save but i didn't profile anything so i should have hit record so i'll hit record here and let's do this again and i'll just remove that extra exclamation mark and save now let's stop the profiler and let's see what we get this is showing everything and notice we've got one of nine screens to look at so we'll scroll all the way down here's our notes list and when it rendered because we memoized those notes the notes did not render so that makes it a little more optimized now let's go to the next changes and of course if we pull this over i think maybe i need to pull this over further devtools at least it can see what caused this update and that says browser router so it'll give us some information as we go edit note so we were at the edit note form and every time we typed of course we got a render there and anything else we did and so it has a few renders now we've got what caused this update it was browser router when we went back but now let's look at the final one and the only render we got was the one we updated so it knew that the other two notes were not updated and we got that final update right here so our react memo is working as we expected as well okay now that we've checked our optimizations i'm going to make this full screen and i'll go ahead and log out and we want to go back to the code there's just a few other changes we could make so here is our react code and we can leave it running as far as that goes i'll just close the terminal window and one thing i'm going to do i'll collapse these directories over here in the file tree but i'm going to highlight this source directory and we could find in all the folders anywhere we have a paragraph that starts with loading and then dot dot dot and that's usually what i would want to replace with that spinner we included and so i will go through and do all of these but just to let you know you could search for that as well or you could also search for that if is loading that seems to appear at all of those so check if is loading and then look for all of those in files and you may want to replace what you have there with one of those spinners instead again i'm not going to show you that i change everyone you can just do it and you can trust that i did it as well okay one final change today i'm going to bring the browser back up notice at the top because a react app is truly a single page app that we make look like it has multiple pages by using react router but notice the title is always react app and that's what's set in our basic html page that's in the public directory however we can create a hook that changes this for each react router page we visit so let's go ahead and do that that's one nice little addition to add at the end of our project i'll go back to the file tree and now we'll go to the hooks directory we're going to create one more custom hook and we'll call this use title.js now inside of use title.js i'll just paste what i have and go over it we need use effect from react and then we're going to receive a title whatever we want the title of the component to be that is currently displaying a page and then we'll use use effect here we'll get the previous title by selecting document.title that's from the dom and then we're setting the document.title to the new title value we're storing the old one in previous title our cleanup function restores the previous title to the document title so whenever the component unmounts it sets the title back to whatever it originally was and we're just looking for changes in the title now this is a true side effect it doesn't have anything else it's returning from this hook and it's really in my mind kind of the perfect react hook it does a simple thing and it sets things back to the way they were with the cleanup function when it is finished so a nice little hook there that we call use title and let's just apply it in the app.js and you can apply it throughout the rest of the project where you want to and you can trust that i will do the same as well so we're going to import use title and now that we have used title this would be our main page and so we just want to put the the name of dan's business which is dandy repairs so we can just say use title and we'll pass in dan d repairs and that's really all you need to do to set the title of the page you're on so we would have other ones like notes list the users list things like that you might want to start all of those with tech notes are something that indicates you're in the back end where employees log in those protected pages and you can do what you want of course you can check the source code that i'm going to link to in the course resources for mine right now let's pull up chrome once again and now you can see we've changed from react app at the top to dandy repairs and so our used title hook is working okay i thought i might get the chance to deploy everything today but we're going to carry it over to one more lesson where we're going to deploy the back end code and then deploy the front end code and take everything online and make sure it's working and of course there's a few changes you need to make as you deploy your project as well remember to keep striving for progress over perfection and a little progress every day will go a very long way please give this video a like if it's helped you and thank you for watching and subscribing you're helping my channel grow have a great day and let's write more code together very soon
Info
Channel: Dave Gray
Views: 11,430
Rating: undefined out of 5
Keywords: code refactoring in react node.js express mongodb, mongodb express react node js, react js node js express mongodb, code refactoring, refactor, code, react, react.js, reactjs, node, nodejs, node.js, express, express.js, expressjs, mongo, mongodb, mern, mern stack, mern project, mern stack project, mern refactor, refactoring react, redux, redux-toolkit, rtk query, rtk, refactoring redux, refactoring code, refactoring node.js, m.e.r.n., mern stack tutorial, react tutorial, full stack tutorial, js
Id: jEVyPJ3U_y0
Channel Id: undefined
Length: 46min 42sec (2802 seconds)
Published: Tue Sep 06 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.