Full Stack MERN Project - Pagination & Search | React + Redux, Node, Express, MongoDB

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

u/HolidayInternet

This was a great video . Loved it. I tried to make a similar application to this by following your tutorial but was presented with an error at the end of Part-1(Post requests)

Request failed with status code 409 error message : undefined source : client/src/actions/posts.js:20

I cross checked my code with the tutorial twice but couldnt find the mistake and atlast cloned the repo and ran ur code . I recieved the same error could you please tell me why i am recieving this ?

Ur help will be greatly appreciated.

👍︎︎ 1 👤︎︎ u/JISHNU17910 📅︎︎ May 28 2021 🗫︎ replies
Captions
hey there and welcome to a project video where you'll build a full stack mirn application our memories project in previous videos you'll learn how to set up a full stack mern project from scratch as well as learn how to add authentication using email and google today you're going to add some new essential features some of the new features are pagination allowing you to only fetch a certain number of memories at a time the second new feature is the ability to search for memories by tags or titles so if i go in here and enter europe and click search we can only see the memories that have the europe tag in them then we can also try with something like the to see which memories have the the in the title and as you can see we have four so that right there was a fully functioning search connected to the database and then serving the resources back to the front end the next let's call it a feature is a complete redesign if you follow the first three parts of this series you know that we had that bluish background only four posts visible at a time but now this is a whole different story we added a logo we made the background look a bit nicer and this is following all the best material design guidelines and finally and most importantly we're going to add client side routing a memory details page you can click on a memory and get more information about that specific memory as you can see we even have the recommended memory section so let's go ahead and check out a few places we have the colosseum in rome we also have the prague castle but you get the point these don't have to be memories or places you have a fully functioning cradmart application and you can turn this into any topic or any theme that you'd like you have a fully working social media application that you can make completely your own if you haven't watched the first three parts they're going to be linked in the description make sure to watch them first and then come back this video is special because it can also be watched as a standalone video that teaches you client-side routing and pagination however i'd still strongly encourage you to watch the first three parts because then you'll have a much stronger understanding of the project we're building as i mentioned before i initially planned on putting this as a paid course but i later decided to release it completely free for you guys here on youtube so to support this video leave a like comment and subscribe it shouldn't take more than a few seconds i really appreciate it on another note some of you in the comments requested me to add some extra features to this application things like comments or even a live chat feature if you'd like me to create a fifth part of the series where i add one of the features you requested make sure to like comment and turn on the bell notifications if this video reaches 5 to 10 000 likes we're recording part 5. with that said let's do a short demo and jump straight into the project i'm currently logged out and as you can see i can view the posts but i cannot like or create new posts to do that i need to sign in or create my account so let's go ahead and click sign in and then you'll be greeted with the sign in form in here we can create a real account in the database sign in with that same account or use google to sign in automatically i've signed in with my personal account and as you can see now we can like other people's posts and we can create a post of our own the memory creation process is incredibly simple you just enter a title message some tags and an image and it's going to be created right away if one of the posts right here was created by you then on the bottom right corner of that card you would have a delete memory button for now let's check some more features i'm going to open a memory details page and then the cool feature right there is that you get all of the similar posts you might like and currently we can see that this is a china and asia post but if we go back and search for a place in europe something like dubrovnik in croatia as you can see the recommended posts are all going to be from europe that's a really cool feature that we're going to implement today one more important thing to mention is that this application is fully mobile responsive and when i say fully i really mean it as you can see our navigation bar all of our options everything is in one column so it's easy to read on mobile devices as well as all of our cards are nicely stacked in one column if you go ahead and click on one you can see that that details page is also going to look extremely clean on mobile devices so without any further ado grab a cup of coffee and let's start adding some new features to be sure we're on the same page when starting the project you can click the github link project learn memories down in the description and that's going to lead you to this page while you're here make sure to start the project if you'd like and if you want to start with this part we're going to go to the branch part 3. why part 3 you might ask if we're doing the part 4 well part 4 contains the finished code for the video you're about to watch so if you have some mistakes in the code if something doesn't work then you can download the part 4. but for now you want to start with the finished part 3 and then we're going to implement all of the part 4 features together in this video so go to part 3 and then you can simply download the code in this case i'm gonna simply download it as a zip folder once the project is downloaded you can drag and drop it to your desktop and then in there we can simply extract it once you've extracted the project you can simply drag and drop it into your code editor of choice in this case we'll be using visual studio code once you're there we can make this a bit bigger and make the text a lot bigger so that all of you can see and you should see the client and the server directory then you can go to view and then terminal and we can split that terminal into two parts we're going to clear both sides the left one is going to be for our client side meaning react so you can cd into client and then there you can run npm install the second one is going to be for our backend or our server so you can cd into server and then there run npm install server side is done the client side is going to take a bit more time and finally when both of these are installed you can simply run npm start in both the client and the server to properly start our full stack application if you've done everything correctly up to this point you should see my demo posts these are some of the most visited places on earth but of course you can connect your own database let me give you a quick refresher on how you can do that you need to create your own database add mongodb atlas then you'll be able to connect it by clicking connect and connect your application in here you can see a string that you have to connect keep in mind in here you need to enter the password and write here the name of your database so let's copy that before we go to our code i also want to show you that you can change your password right in here database access edit and then edit password once you know your password you can go to server index.js scroll down right here you can see the connection url feel free to delete my url and simply paste yours right in here great with that said we are up and running with the old version of our memories project you can see that we have this playful bluish background we have no pagination which means that you always have to search and query hundreds of posts display them that's why pagination is one of the best things that we are going to do we also have no search so if i go to the top you can see we cannot search for posts we cannot click on a post even to see what it is about so this video is definitely going to be good let's start creating the code to prepare ourselves for all the dependencies that we're going to need we can open up our terminal press ctrl c to stop it from running and then right in here we can install some of the dependencies we're going to use in this video we can say mpm or yarn install and then we can say add material dash ui forward slash lab we're going to use this for pagination and some other things and finally we're going to install material dash ui dash chip dash input that is going to be our input for our tags and that's it you can press enter and once that installs you can bring this application back to running by pressing npm start and with that we can close our terminal and start creating the front end a smart place to start would be to create the pagination component so we can go to client we can go to the source and components and then right inside of here we're going to create a new file called pagination.jsx inside of here we're going to import react from react as we always do we are also going to import some of the components from material ui lab we can say import and that's going to be pagination as well as the pagination item and this is not being imported from material ui core because these are still experimental features so we're importing them from the material ui lab library of course we're going to have some styles so you can say import styles from dot slash styles and of course you could have done this in a folder but in this case i'm just going to do them right in here and that's going to be styles.js the styles for the pagination component are going to be incredibly simple we can say import make styles from add material ui forward slash core forward slash styles this is how we usually do styles in material ui finally you can say export default make styles and then in there we call that as a function and provided a callback function that instantly returns an object like this it is a bit of a weird syntax but we have to do what we have to do inside of there we'll have only one class called ul and then it's going to have the property of justify content is equal to space round great that's going to be it for the styles now we can go back to the pagination component and continue working on the jsx our pagination is going to be a react component called paginate and it's going to be of course a functional component inside of there we're going to use our classes by saying cons classes is equal to use styles and then we call that as a function and at the top this should have been used styles and not styles great so now we have the classes now what are we going to return well the return is going to be the pagination component that we are importing right at the top that pagination is going to be a self-closing tag but it's going to have a few props the first prop is going to be classes and classes is equal to object and then inside of there ul is equal to classes dot ul moving further we're going to have a count this is the number of pages in this case we can make count equal to 5. this is just a static amount but we'll have to dynamically fetch the number of pages depending on the number of posts we currently have then we have to have the current page in this case let's only say something like one of course this is later on going to be dynamic as well then we're going to have a variant which is going to be simply a string of outlined we're also going to have a caller which is going to be equal to primary and we're going to have a render item property which is going to be a dynamic block of code with a callback function inside of there our callback function is going to take an item as a prop and we're going to instantly return something so we're not going to use curly braces we're going to use immediately simple parentheses the thing we're going to return is going to be a pagination item which is yet again a self-closing tag inside of there we're first going to spread the item so we want to pass all of the data from the item right inside of the pagination item then we're going to say that this pagination item is going to be a special link component that we are importing from react router dom so we can say import link from react router dom great we're going to use this for routing and then finally we have to see where is this pointing to so we can say 2 and that 2 is going to be equal to a dynamic string of course and then inside of there we can say something like forward slash posts and then question mark page is equal to and then a dynamic page which is in this case going to be 1 but later on we're going to have a real dynamic link now if we save that of course we have to do export default paginate and with that said our currently static pagination component is now done so we can import it somewhere and start using it we are going to import it inside of our home component inside of there we're going to import pagination from dot slash vagination in this case we don't have to do pagination forward slash pagination because it's not in a special folder great now that we have it let's see where we can actually call it i'm going to scroll a bit down and then in here just below our form we want to call our pagination but we're going to call it inside of a paper component that paper is going to be coming from material ui so just at the top we can import that paper paper is just a white div that paper is going to have a class name that is going to be equal to classes dot imagination it's also going to have the elevation equal to 6 which is going to give it a nice shadow finally inside of there we can call our pagination component of course it is a self-closing tag as you can see currently we don't have classes in there so i'm going to delete that and we're going to do that later because we have to do a refactor of the entire home component now if i save this and go back as you can see just below this form doesn't look that pretty but we have our pagination component with five pages as we specified currently if we click that nothing is going to happen because we are navigating to forward slash posts question mark page is equal to one but our current client side navigation doesn't know what that is because all the posts are simply on localhost 3000 so we have to make our client side navigation and react router work with the current new pagination system first of all we're going to import one more thing here from react router dom and that is going to be a redirect component then we can start working on the jsx i'm going to change this from lg large to xl which is extra large because we want to fit more posts on the screen then we have our nav bar and then we have our switch so first of all we're going to have a path just slash which usually renders first on the page we don't want to render a home component there what we want to do is call a callback function which is simply going to call the redirect component and that redirect is going to redirect us to and that's going to be forward slash posts so we only want to see posts if we are on this specific path and we're going to be immediately redirected if we do this of course we have to keep in mind that if we want to show something on this specific route we also need to create it so just below the current route i'm going to create a one more self-closing tag this one is going to have the path of forward slash posts it's also going to have the exact parameter and it's going to render the component called home before we're rendering the home component on the just slash path we can now copy and paste this home route just below because we also want to render the home component if we are on the forward slash posts forward slash search this is going to be rendered when we are searching for something and then in here we'll be able to provide some more parameters like search query and so on but for now it's important for us to have this right here then below that we're going to have one more route that route is also a self-closing component that has the path which is equal to forward slash posts and then finally forward slash column id this is going to be the post details path and this column id means that this id is going to be dynamic finally we're going to render a component called post details of course we haven't yet created or imported postdetails component so let's do that right now inside of our components i'll create a new folder called post details inside of there we can create a new file called post details dot jsx and inside of there we can create a new react component we can use the rafce this is the extension for es7 react redux snippets so i'm going to use that which is simply going to generate a react component for us but of course you can write this by hand if you want to for now in there we can simply put a console log that's going to say something like post details and we can also just render a string of post details in the jsx just so we can see if our component is showing up now let's go back to the app and then in here let's import that post details component by saying import post details from post details i just want to point your attention to this nice tool i've recently started using which is called tab 9. you can see it's using ai to autofill code and it immediately knew that i wanted to autofill this exact thing which is kind of crazy if you think about it but with that said we are now creating and importing post details and we are pointing to it when somebody goes to posts and then a specific id let's see how that looks in action if we try to remove the forward slash posts and just check the localhost 3000 and click enter that's going to point us straight back to forward slash posts exactly how we want it then we also added the forward slash search that works we are right there and then we also added a specific post page post details and in there we have to enter some id right now it doesn't matter which id we enter so let's try it one two three and as you can see if i zoom it in we have our post details right in here finally we have our forward slash auth page which is going to be our sign in form if you open that up an alert is going to pop up and the reason why is because we haven't connected a real google sign in to see how you can set up full google authentication make sure to watch the third part of this series because there i teach you how to do exactly that for now to get rid of that alert we're going to go back to our auth which is in components and then auth right there we're going to scroll down a bit and we can see this alert we're simply going to swap that into a console.log for now that way the alert is not going to pop up if you don't have the valid google console connected but then again if you want to connect it you just have to watch the third part of the video and you're gonna have a valid id to connect it with with that said this is our odd route if i enter my email and sign in you can see that everything works right but somebody can still go to forward slash auth and see this page that shouldn't be the case if we're currently logged in we should only be able to see this if we're logged out so let's fix that we can easily fix that by going to app.js and then inside of here instead of rendering the auth we first want to check if the user is logged in and we can do that because we are storing our user's information in local storage so i'm going to switch this from a parenthesis to a code block and i'm going to put all of this part inside of the return of this component so just here we're going to have a return and we're going to put all of the code here but before we do that we're going to have a const user which is equal to json.parse and we want to parse the local storage dot get item and we want to get the profile that way we'll have the access to the user variable now depending of the state of the user we can render something different here instead of the odd so we can have a callback function and then there we can say if no user then we want to render the odd component that makes sense right we want to render the auth if the user isn't logged in but if they are we simply want to redirect the user so redirect that is a self-closing component that's going to point to forward slash posts just like this let's see if i have that correctly that looks fine to me so now if we go back and if i try going to forward slash auth it's simply going to redirect me back to posts great that was our refactor of the app.js component now we can start with the refactor of the home component so that we can accommodate it to use the pagination let's navigate to the home component and let's see what changes do we have to make they're going to be quite a few because a home component is going to be a really important component that's going to handle the logic for the pagination and some other stuff so let's make our life easier by first importing all the things we're going to use we're going to import a few things from material ui and those are going to be the app bar the text field we're going to also use a button and finally a paper which we already have right there then we're going to import some things from react router dom these things are going to be called use history and also use location we're going to use that so that we know on which page are we currently and we're going to use the history so that we can re-navigate to certain pages and search terms that's going to be imported from and that is going to be react router dom inside of here we're going to also use something known as a chip input and we're going to import the chip input from and that is going to be material ui chip input chip input is a normal input but it works great for tags let me show you what i mean right here on the top right i can search for tags let's do europe and you can see this is not a general input this is a chip input so it turns it into this spill-like structure we can also search for asia we can search for usa and all of these are going to be in so called chips so that is what we'll be using for our tags we also have to set up our url search params we're going to use that to know on which page are we currently on and what search term are we looking for to do that react router dom says to use a function and call it use query that use query is just a normal function and in there we are returning new url search params we call it and pass use location which we call again and call the dot search after that that simply allows us to use it as a hook so we can simply say cons query is equal to use query as you're used to we also have the use history so we can say const history is equal to use history query is where we'll be getting our page info from so you can say something like const page is equal to query dot get and then in here we can say page so this is going to read our url and see if we have a page parameter in there if so it's going to populate this variable so we can say that or one so if you don't have the page we must be on the first one finally we're also going to have a search query so we can say cons search query is going to be equal to query.get and that's going to be search query great now we have some of the things that are necessary and now let's modify our jsx the first thing that we're going to modify is that we're going to have our container and that container is going to have a max width equal to xl then we have this grid container and the only thing we're going to do with it is we're going to give it a class name the class name is going to be equal to classes dot grid container for now we don't have classes but don't worry we're gonna import them really soon then we're gonna have our grid item and in this case we're going to make it a bit more mobile responsive by saying take 12 spaces on mobile then take half the screen on a bit larger devices and finally on medium devices so take three quarters of the screen on bigger screens we want our posts to take most of the screen finally on this screen where we have our options like the form and the pagination we can leave this as 12 then on small devices that's gonna take the half the screen and on medium devices it's the screen is big enough so three spaces are going to be just enough finally we're gonna make this look a bit better because now we have the form we have the paper pagination and soon enough we're going to have the search as well so let's add something known as the app bar app bar is going to have a class name equal to classes.app bar search it's also going to have the position which is going to be equal to static and it's going to have the color which is going to be equal to inherit inside of that app bar we're going to have our search so inside of there we can create a text field that's going to serve as our search the text field is going to be a self-closing component and it's going to have quite a few properties the first one is going to be the name which is going to be equal to search then it's going to have a variant which is going to be equal to outlined then it's also going to have a label our label is simply going to be something like search memories we have many props for text fields i'm going to put them all in separate line then we're also going to have a full width prop we're also going to have the value which is going to be equal to a search for now we can say something like test then we're also going to have the on change property which is going to change our value so for now i'm going to leave it as an empty function like this and that's going to be it so now let's add our classes and we'll be able to see how this looks like in action as you know the procedure for adding classes is similar so we can simply say import use styles from dot slash styles that's it and finally we need to create the styles.js file inside of the home folder as always to save your time i'm going to simply give you the code give it the styles to simply copy and paste them it's nothing special adding some border radiuses some display flexes padding margin and so on nothing scary you should worry about but just to save some times you'll be able to find all the styles i mentioned in this video down in the description so just go ahead find the link and paste them right in here once you're done with that we need to call our use styles as a hook so we can say cons classes is equal to use styles and we call it like a function now if we save this we shouldn't have any errors and we can check it out in the browser and that already looks so much better take a look now on big screens our posts are taking more of the width and we have our search on the right side which already looks good of course we cannot currently type in it because we have a constant value in react we have to manage the fields using state so let's create a state field for our search memories field we can scroll just a bit up and then in here we can say const search and set search is going to be equal to use state and then inside of that state the default value is going to be an empty string now let's use that state variable and put it right here instead of this static test value and let's do something on change so what do we have to do on change well we get the event and then inside of there we can say set search is equal to e dot target that value that's going to allow us to change the value of the search one thing that i often prefer is not having the need for a button so we also want to make something happen if we click the enter key so let me show you how we can do that we can add just one more thing onto this text field which is going to be called on key press and then on key press we're going to create a function called handle key press that function is going to be just right here below this use effect const handle key press it's going to accept an event that's going to be a key press event and we can simply say if e dot key code is equal to 13 in that case we want to do something we'll want to search for the post for now we don't have to logic to search for the post but i'm going to add the comment search post right here so we can add it later on key code 13 simply means the enter key so to know if the key code is 13 you press enter great now before we add the search post functionality i also want to add the jsx for the search by tags to do that we're going to use the chip input we imported at the top our chip input is also going to be a self-closing tag and it's going to accept a few properties first it's going to accept some styles you can have an object in there and say margin is equal to and then a string of 10 pixels top and bottom and 0 pixels left and right we also need a value for our search and this value also needs to be dynamic it has to be from state so let's scroll to the top and let's create a tags state field i'm going to simply copy this line replace this for tags and set tags and at the start it's not going to be an empty string it's rather going to be an empty array because we want to have multiple tags now scrolling down we can add the value of tax we're also going to have the on add function and the on the lead function for now we're going to leave this as empty and we're going to populate them soon we also need to have the label which is going to be equal to search tags and we also need to have a variant which is going to be equal to outlined just so it matches the text field on add we're going to call the function called handle add and then on delete we're going to call a function called handle delete and of course we have to create those functions so scrolling a bit up right in here we're going to create that function const handle add and it's going to accept a tag as a parameter finally what we have to do is we have to call the set tags state and then inside of there we're going to have an array as the state when you have an array with states you first have to spread the previous tags and then add the new tag onto it this is how we're going to handle the add tag and finally let's also handle the delete so we can say handle delete that is also going to accept a tag but more specifically tag to delete and what we have to do is we also have to set tags but inside of there we're going to say tags dot filter where we get one specific tag we can put it like this tag and we want to filter out the tag to delete so we can say if tag is not equal to tag to delete we're going to keep all the other ones but we're only going to delete the tag we want to delete now let's add that there we have a handle delete and a handle add function let's save it and see how does it look like as you can see we have search memories and we have search tags let's try adding test a tag appears let's try test one test one appears and we can finally test it by deleting them which also works final thing of course is to add a button that's going to do something with those inputs a button is not going to be a self-closing tag it's going to have the on click property and on click we want to do something and that something is search post search post is a function we haven't created yet so then we can create a class name which is going to be equal to classes.search button and we can also have a caller which is equal to primary finally inside of the button we're going to say search now if we save this and take a look it's not going to work because this is undefined so we have to create that search post function we can create a search post right here below the use effect so const search post is equal to a function which doesn't accept any parameters inside of there we want to see if we have a search term so we can say if search this search maybe is not the best name a better name would be something like search term or title or something like that but in this case it's search and we also want to trim it to make sure there are no empty spaces so if we have a search term then finally we want to dispatch some logic to fetch our searched post so fetch search post great of course to dispatch this we're going to have to use redux and we're gonna have to modify our database to only search for specific posts and else if we don't have a search term then we're gonna simply use the history object and call the push method to forward slash we just wanna redirect back because we have searched for nothing and as you can see here we have this comment we also want to call for the search post function right inside of here if we press the enter key now that we have this let's take a look in the browser we have our two inputs but the search button doesn't look right looks like we're missing something the thing we're missing is going to be the variant equal to contained let's save it and take a look search memories search tags and they search button but of course if we search something right now nothing is going to happen but now comes the hard part we have to tell the database to only return us the posts that match our query to send a nice message to the database we can use redux so let's first create a redux action and a reducer to manage our posts this patch is the verb that we use with actions so to have something to dispatch we need to create an action for searching the posts to do that we can open up our file explorer go to actions posts and then inside of there just below our previous get posts we want to create an action called get post by search so we can say export const get posts by search that is going to be a function and it's going to have this syntax as you can see as all the previous actions do we're using redux tank for asynchronous actions and again tab 9 does a wonderful job of just immediately filling this out for me again the link is going to be down in the description so you can check out tab 9 maybe install it as a visual studio code extension and let's see how do we want to fetch the data well as before we're going to have a try and catch block so let's create it try and catch and then in the try we want to do something like const where we get the data inside of the try block we want to try to communicate to our backend so we can say cons we destructure the data and that is going to be equal to await api dot fetch posts by search which is a function of course our get post by search is going to accept a search query as a parameter and we're going to pass that same search query to our api request for now we're simply going to console log the data and we're also going to console log the error if there ever is one now we have to go to our file explorer api and then index.js because we have to create the api endpoint called fetch posts by search so let's go right there and then just below fetch posts we can create our fetch posts by search it's going to be really similar so we can say export const fetch posts by search this time it's going to be a function but it's going to accept a parameter of search query finally we'll be making an api dot get request to forward slash posts but we have to provide some information about our search the endpoint is going to be four slash posts for slash search but now inside of there we're gonna use query parameters query parameters start with a question mark and then you specify a variable name search query and that search query has to be equal to something so for example you can pass a static value of test but we're gonna make it dynamic so i'm gonna make this into a dynamic template string and then we're gonna use the dollar sign curly braces syntax to make this equal to be search query dot and then we're going to use the search and if there is no search then we can say or simply do a string of none but we also want to add something else so after that we can say end and now we want to handle our tags it's going to be the similar situation tags are equal to and then inside of there we can say search query dot tags and now we're sending all of the information to our search endpoint great now we have our endpoint and we also have our action so we can go back to where we were to home and then from here we can dispatch that action we can first import it right here it's called get posts by search and finally we can use it right here in the same way we used get posts that is going to be equal to this patch we pass the get post by search and we call it as a function but remember this action is going to take in some parameters more specifically it is going to take the search query object as we specified inside of that search query we have to provide our search which is coming from state as you can see here but we also have to provide tags which we have to render into a string because we cannot pass an array through the url parameters because of that we're going to do tags is equal to tags that join and we're going to join them by a comma that way if we have an array of something like let's say that we have tags of europe and let's say usa that is going to be equal to a string of europe and then comma usa if that way we'll be able to more easily pass the data from the front end to the back end now we have the action we are dispatching that action we're making an api request let's just remember to which endpoint to forward slash posts forward slash search with some parameters so let's create that endpoint on the back-end side we can go to our server folder and inside of our server we are going to go into routes we first have to create that post route we can create it just above our get posts and remember it is going to be to forward slash search before we set it's going to be forward slash posts forward slash search but remember since we are in the post.js file all of these routes begin with post even though you cannot see it right here okay and on the search route we want to call a specific controller so just at the top we can import it get posts by search and we're going to call it once we get to that route and finally we have to create that controller where most of the logic will happen so let's go to the controllers posts and then just below the get posts we currently have we're going to create a new controller export const get post by search that is going to be an async function of course we have the rec and the rest in there and we also have a try and catch block now we want to retrieve that data from the rec.query remember that i mentioned params but params and query are actually two different things let me explain what i mean when we have a query that usually means that the route goes like this forward slash posts question mark page is equal to one in this case we would have a query where page variable is equal to one but if we have something known as params in that case our route would look like this forward slash posts and then forward slash colon iv in in here you would be able to put your specific id let's say one two three and in that case the populated variable id would be equal to one two three both ways are fully okay usually we use query if you want to well query some data like search and we use params if you want to get some specific resource like posts and then forward slash id of the post i hope that makes sense and that i explained it in a nice and easy to understand way if you like the way i explain things make sure to leave a like and let me know in the comments i really appreciate that and if you really want to be generous there is a buy me a coffee link in the description and that really allows me to keep creating more great videos for you guys with that said let's keep creating the logic for the search right at the top we're gonna get the data from the query we just talked about const we get the search query and we also get the tags because these are the two things that we passed and we get them from reg.query now let's convert our title into a regular expression by saying cons title is equal to new reg x and then in there we're going to pass our search query and a flag of i i stands for ignore case that means that if you search for something like test or test or test it's all going to be the same it's not going to matter and we want to do that we want to get all the posts that match our search term we converted it into a regular expression in the first place because that way it's easier for mongodb and mongoose to search the database so let's search the database for posts by saying const posts is equal to a weight postmessage dot find now in here we have to write that query which is a bit more complicated but don't worry inside of here we can open a block of code where we're going to have the dollar sign or that or stands for either find me the title or find me the tags we want to find the posts that match either or so we can make that into an array and then the first thing in there is going to be the title so we're matching for the title the second thing in that array is going to be the tags we want to match the tags but keep in mind there is an array of tags so inside of there we're going to open another object i know it's getting a bit complicated and we're going to say in is there a tag in this specific array of tags that matches our query in there we can say in tags that split and now we have to split them by a comma because remember before we joined it just so we can send it over in a nice string i know it's a bit complicated but let me try to explain it one more time in plain english find me all the posts that match one of those two criteria the first one is the title is the title the same as we typed it on the front end and the second one is is one of the tags in the array of tags equal to our tags if that's the case then we want to display those posts finally once we have the posts we have to say res.json and then in there we'll have an object where data is going to be equal to posts and we're sending that back to the front end finally if we have an error we can simply return it to the front end by saying press that status that's going to be a 404 dot json and there we're going to have an object that has a message equal to error dot message so now let's go back to our action creator and check if we're receiving the data that's going to be right back to our actions in here and we'll have to destructure the data two times first time because we're making an axios request and the second time because we put it in a new object where it has the data property just like this finally we're console logging the data right here so let's go back to the browser and see if all the logic that we wrote right now actually works usually it is a miracle when everything works first time but who knows let's give it a shot so i opened up a console i am on my localhost 3000 forward slash posts and i want to search for the word the because we have it a few times in the coliseum we also have the acropolis so let's see if it finds it i'm gonna click search and take a look at that we got back an array with four different objects representing four different posts the first one has the message of the most famous as you can see it right there the colosseum then we have the acropolis taj mahal also has the word the and finally the most famous paris museum also has the word the so that means that it works now let's see if our tags work i'm going to remove this and then in there i'm going to type something like europe if i search now we should get one more response but unfortunately i don't see anything so let's go back to our search form and see why is our search button not working for tags this is going to be a good debugging session opponent responsible for our search is going to be our home and right in here we can see that we indeed are dispatching the get post by search but it's a simple logical error i'm simply saying if there is a search term then this patch but we have to make it if there is a search term or if there are tags if we just add that that should fix the problem search for something like usa and click search we get three posts back this is going to be the statue of liberty in new york then we have the grand canyon and finally we have niagara falls which is bordering the usa and canada if that means that our tag completely works we're seeing the data in the console but now let's make it display that data and change the url on the client side doing that won't be that hard because we already set up most the logic to finalize it you can go to the components and then to our home component inside of here after the dispatch get posed by search we only want to do one more thing and that is to use the history dot push method to push our website to a specific url more specifically we want to go to forward slash posts for slash search question mark remember question mark is for the search query parameters we can say search query is going to be equal to search right the search is something that's coming from the state or none we can use a string of none if there is no search and then finally we're going to use the and symbol to set the tags tags are going to be equal to tags dot join and we're going to join the tags by using a comma remember we had to split them and then join them to use them again great this seems okay to me so let's see if we are being pushed to that specific url if i go in here and use the as an example as well as the europe as a tag let's see what are we going to be pointed to as you can see our url changed search query is now equal to the and tags is equal to europe we're going to use that to form our posts but why does this url on the client side even matter we formed it for the backend okay but why do we need it on the front end well let's say that you search for some memories and you want to send to your friend only the specific search term with the terms and the tags already put there that way you can simply copy this paste it over and he's going to get the relevant information that's why we need client-side routing okay so now let's display those posts to display the posts we're going to go back to actions and we have them right in here so we have to do a similar thing to what we are doing right here in get posts i'm going to copy this and we're going to do it in the same way but we're going to rename our dispatch action type so let's create a new one by going to constants action types i'm going to copy this line and we're going to change it just a bit to something like fetch by search great so now we have one more constant we're going to go back in here i'm going to import it fetch by search and we're going to use it right inside of here and again we're sending the data to our reducers so let's go to our reducers posts and then right inside of here we're going to add one more case that case is going to be fetch by search and we can also import it right at the top now that we have that case of course we want to return something if that happens so we're going to return a similar thing in this case it's just going to be action dot payload now let's see what we're missing if i add that there that should be working let's go check it out we're back to just forward slash posts but i'm gonna search for something like asia i'm gonna click search and as you can see now we got all the posts that have something to do with asia asia right there there there and everywhere that is great that means that our search works we can also try it by the title if i click search it's going to take a bit and as you can see we have all of the posts that have the in the title that means that our search works perfectly now that we have that done before moving on to pagination and loading states let's do something easier like changing the background and the logo at the top and then inside of there i'm gonna remove both of these background colors and we're simply going to say background color is going to be equal to hash symbol and then f7 f8 fc this is a whitish color almost pure white now if we save that and go back you can see it looks a bit more professional maybe a bit plain right now both the background and the card are pretty much white so to make some separation let's add some elevation to the card we can do that by going to posts post and then finally pose.js finding our card component and then inside of there we're going to say raised and also set the elevation to be equal to six that's going to add this nice shadow that you can see at the bottom of the card which separates it from the background i can also see that we still have only two cards per row so let's make it like it was at the start of the video to do that we're going to go to post js this time and then inside of here we're going to say show 1 which is 12 spaces on extra small devices still show one on small devices on medium devices show two per row but on large devices show four per that's three times four is equal to twelve and that is four per row let's see how does it look like this is already so much better in my opinion everything fits on one screen as you can see we currently have no pagination so we have quite a long list of posts now that we've changed the color the things that jumps out a bit too much is the memories logo at the top so let's change that as well to change it we're going to go to the nav bar and right in here instead of this memories png we have to add two new ones i'm simply going to open the images folder and then i'm going to paste it the links to download both of these are going to be in the description so that you can download them as well but once you actually do that we can go back to our nav bar and inside of there we're gonna have memories logo imported from memories logo and we're also going to have memories text imported from memories text now we can use those two images to make it look a bit more professional we can do that right in here we are no longer going to use this typography so we can delete it we are going to use two different images the first one is going to be the image self closing tag right inside of there the src of that image is going to be memories text like that and it's also going to have the alt tag of icon it's going to have the alt tag of icon and it's going to have the height equal to 45 pixels the one on the bottom is going to have the class name of classes.image it's going to have the source of memories logo and the height is going to be equal to 40 pixels finally once we have that we want to transform this div into a link so i'm going to say link there more specifically link to and then we want to point to just slash now let's save that and see how does it look like in the browser there we go this custom logo just gives this project a bit more character i can see that the second image is a bit higher up than the first one so we can go to the styles and i'm gonna leave this style as well you can simply override it it's going to be down in the description i've made only a few small changes since the last video but then again make sure to copy and paste it just we're on the same page if you go back to the browser you'll notice that now they are aligned now that they've made the application look a bit better and now that the search is fully functional we can focus on pagination and loading states currently if i go back to the home there won't be any loading it's going to happen instantly but take a look we only have three posts and now they pop up so something doesn't seem right it's always good to have proper loading states so that your user knows that something is happening so pagination and loading states coming up we already worked a bit with getting the page and the search query from the query parameters but now let's put that page to use we will no longer fetch the post from here from the home we're going to remove this use effect and we're going to pass our page straight to our pagination as a prop so in here we're going to say page is equal to page that way we can go to our pagination and we can get it straight from props now inside of here we can create a new use effect so i'm going to say import use effect from react and we're going to declare it right in here our use effect as always it is a function with a callback function and has a dependency array so what do we want to do inside of that use effect well we want to fetch the posts any time that the page changes to fetch the posts as always we're going to use our dispatch with redux so we need to import a few things from react redux we can say import and that is going to be use dispatch so we can dispatch things and also use selector so that we can select some things from our state and this is going to be imported from react dash redux we also want to import an action called get posts so we're going to say import get posts and that's going to be coming from dot slash actions forward slash posts of course to get our dispatch function we can say const this patch is equal to use dispatch and then call it as a function now instead of this use effect we can say run it every time that the page changes so every time that the page changes if there is a page in that case we want to dispatch a specific action in this case we want to dispatch the get post action and let's open up that action side by side here just so you can see how it looks like get post you can see it accepts no parameters and in its current form it fetches all of the posts but that's not how we want it to behave we want to pass a page to it so that it only fetches the posts for that specific page and that's exactly what we're going to do right inside of there we're going to pass that page in now inside of our actions we can accept that page as a parameter once we have it as a parameter we can then pass it over to our api as well so inside of here we can pass that page of course now we have to go to that api and make some use of it so let's open it up in full screen as you can see fetch posts but now that function accepts a page and we can use that page to then filter it out so we can say api.get forward slash posts and then it's going to be question mark page is equal to dollar sign curly braces page that we're getting from the parameters of course we have to turn this into a template string and that's it now we're passing the data to the backend just so we know on which page are we currently on now let's go to the backend and modify our controller so that it returns only the data for that specific page that's going to be inside of the server and then finally inside of the posts controllers inside of here we have our get posts but that's basically now get post by page we can do similar thing that we did with reg.query we're going to say const this structure the page and that's going to be coming from rec.query because we're passing it through the query from the front end now we're going to have some extra logic in here just before we call the dot find on posts first we're going to declare a variable called limit the limit is going to be the number of posts per page i decided to make it 8 but you can change it if you want to then we have to get a start index of a post on a specific page for example the start index of the first post on the third page would be 8 plus 8 plus 8 minus 1 because we start from 0 and that would be 23 so let's create that first we have to convert our page into a number using the number constructor even though the page is a number on the front end when we pass it through the reg.query it becomes a string so we have to convert it back and now we are simply going to deduct -1 from that and finally multiply all of that by the limit this way we're always going to get the start index of the post on a specific page we can even write a comment right there get the starting index of every page great finally we also need one more variable which is const total that is going to be equal to await postmessage dot count documents we want to count up all the documents so that we always know how many documents do we have how many posts do we have why do we need to know that well depending on that we're going to have a specific number of pages and we always need to know what is the last page we can scroll to that's why we have the total variable now that we have the total finally is the time to fetch the posts so i'm going to rename this from post messages to posts and let's see how we can do it well we can say await post message dot find then i want to get the posts from the newest to the oldest because of that we have to sort them by id so i'm going to say dot sort we're going to pass in an object and say underscore id is equal to -1 this is going to give us the newest posts first then i also want to limit them so we're going to call the dot limit on that and we're going to pass in the limit variable this is going to make sure to only give us for example 8 or 10 or or however many you choose per page and then finally we need to skip all the previous pages for example if you're on the page 2 you don't want to fetch first 16 posts again you want to skip the first eight and because of that we're going to use the dot skip and we're going to skip all the way to the start index now we understand why did we have to create all these variables it all makes sense hopefully finally for all of this to make sense to the front end we have to pass a bit more data than simply posts so i'm going to pass a new object and inside of that object we're going to say data and the data is going to be equal to posts we also have to pass the current page which is going to be equal to number of the page so we just make it into a number and we pass that page and finally we also want to have the total number of pages that is going to be equal to math.seal and in there we're going to divide the total by the limit great that is going to give us the total number of pages now we're passing all of that data back to the front end and we have to make use of it of course where better to do that than in the action that we declared so i'm going to go back to our posts action before we were getting just the data for the posts and we're immediately passing it here but now that data is going to contain more info so let's see what is contained in that data object if i open up the console the current page is one the total number of pages is three and this should have been pages plural so i'm going to go back and just change that to pages what we had before was simply a variable that contained all the posts that means that we have to change the way our reducers view and render things the only thing you have to keep in mind here is that our payload is no longer just posts it's an object that contains three different things as we saw previously it contains the data of posts it contains the current page and also the number of pages let's go to our reducers which is going to be in here reducers and posts instead of simply returning the action.payload we have to return an object so right there i'll say return put that into an object and then i want to spread the current state these posts here are going to be more than simply an array of posts so i'm going to rename this to state you'll see soon enough why first we want to always spread the state when we're working with objects then we want to get our post and now posts are not simply action.payload posts are equal to action dot payload dot data then we also have a current page our current page is going to be equal to action dot payload dot current page and finally we have number of pages which is going to be equal to number of pages again tab 9 really auto fill that easily great so now we're turning something different from the fetch all reducer it would be great if we immediately also accommodated the fetch by search in the same fashion so in the fetch by search we also have to make it an object inside of that object we're going to spread the state and then we're going to say posts are equal to action dot payload dot data you can also see that we are mentioning the post a few more times here i'm just going to replace all of these with state considering that i renamed it at the top right here in our fetch by search this is not going to be action payload data it's going to be simply action payload that's where we have our posts considering that we've changed the structure of our state we have to find where are we actually using that state so that we can change it there as well let's search for use selector that points to us using the state we can see that it's being used in pagination but we're never actually doing anything with it then it's also being used right in here in the form and finally this is the one we're looking for use selector in the posts here is where we are using the posts before we simply had an array of posts but now we have an object where we have a property of posts inside of there so we have to destructure the posts right in here and the main reason we change this from an array to an object with multiple things is because we are gonna have multiple things we're gonna have the is loading property we're gonna have the number of pages and so on but for now we simply need to destructure this we can also add a question mark here to make sure to not throw an error if we don't have any posts available now let's save that and let's see if this is going to work we are back on our memories project and would you look at that we can see all of our posts that's great let's see if we can also see the posts that we search for for example let's search for europe again and it works we waited a bit but it finally gave me the posts that's great but that's something that worked before right so why even check it well we checked it because we changed a lot of things and you want to make sure that when you change some big things you check if you've broken anything but now is the time to check the pagination it's not going to work yet because even though we implemented all the logic for it we have to do one more step and that is use that logic inside of the pagination component so let's go back to it and do it inside of the pagination component we can now use this use selector to get the number of pages to do that we can say const the structure number of pages and make that equal to use selector inside of there we have a callback function where we get the posts and we want to retrieve state dot posts that is the reducer that's going to have the access to the number of pages finally we want to use that number of pages variable right in here under count number of pages only that we also have the access to the current page right in here so we can simply say right there number and page and just to be sure if we don't have a page we want to render or one to be on the first page i also noticed that right now i specified right there you select that is going to be use selector also in here posts page 1 in there we want to navigate to item dot page with these small changes we've made our pagination component completely dynamic let's see if it works going back to the browser first thing that you can see is that we have only three pages and that is correct because we have less than 24 posts let's try to go to the second page as you can see the url changed and even though it seemed for a second that nothing is happening because we don't have the loading yet it worked we got the second batch of posts finally let's go to the third page and there we go we got five more posts that means that our pagination fully works so we can switch between the pages and we can render only eight at a time this is incredibly important imagine that your application is used by hundreds or even thousands of users and that each user creates tens or even hundreds of posts imagine if your application had to load all 10 000 posts at once it would take so much time but why even do it when you can only see eight at once that is why we use the pagination to cut down on low time anyway great work pagination seems to be done at least from what i can see right now hopefully there aren't any bugs and now we can move to the loading states to start working on our loading states you can head to posts actions redux makes it quite easy to have one central source of truth so we always know are we loading or are we not that's why we're going to use redux to accomplish the loading states so right inside of here we're first going to create two more constants action types right in here i'm gonna create the export const start loading that's going to be equal to a string of start loading and then finally we're gonna have one more which is going to be called end loading we're going to use this action types so that our redux reducers know when to start and stop loading we can go back to our action posts and we're going to import them right here at the top start loading and end loading the only question we have to ask ourselves is when do we want to start loading well as soon as we call get posts just before we try fetching the posts right in there we can say this patch and the only thing we want to dispatch is an action that has a type of start loading that's going to be it and when do we want to end the loading well it definitely has to be after we fetched all the posts which is going to be right here dispatch type and loading of course we want to have the loading state in a few more places also when we try to get post by search and so on so we can copy this start loading and we can paste it in a few more places before we try to get post by search we want to have it there we also want to have it before we create a post on update we're not going to go anywhere we're just going to update it so we don't have to have it there for the like that's the same thing and for the delete that's also the same thing these actions by themselves are not doing anything we have to go to our reducers and then there create the logic for our loading states inside of here we're gonna also import start loading and and loading or is it stop loading let me see how i called it it start loading and then we have the end loading i also forgot to put it here at the end of the fetch by search so i'm gonna import it and loading and now we have to add it here at the top so what happens if we want to start the loading also what happens if we want to end the loading we're going to prepare those cases and let's see what data do we want to return well of course we want to return an object as we always do we want to spread the state that we currently have and we only want to change the state of one variable and that is is loading is going to be equal to true if we want to start the loading and then we can copy this and paste it below same thing but we're gonna change the is loading state to be false that's all that you have to do to manage loading in redux you don't have to do it everywhere in your code in all of the components whenever you do something cover the logic with changing the state you only do it here and everything is being done right here inside of actions it might be a bit confusing at the start but as you get more into it you'll start seeing the purpose in that back in reducers considering we change the way we view data we also have to change this state the state is no longer just going to be an array of posts it's going to be an object that's going to have the is loading property and that is loading is initially going to be set to true and also we're going to have the posts array great now that we've changed this we also have to change how do we get the data back once we like create update or delete posts the only thing we have to do is we have to everywhere spread the state so right here i'm gonna try to select multiple lines by holding alt and clicking at the start of each line right there i'm going to open up an object and first thing that we want to do everywhere is we want to spread the state as we always did finally once we spread the state we want to set the posts inside of that state to be equal to what we previously had right there and then finally make sure to add the closing bracket at the end here here here and here i know that it might be just a bit confusing but we are basically switching from using just posts as an array to having an object that now contains the is loading state as well as the post state so that's why we have to turn this into an object spread the entire state and then finally only return the posts and also notice how we're doing stay that map spreading the state state that map state that filter that's no longer going to be possible rather we have to do state and then dot posts and then dot map or that filter or anything so just to fix this we're doing state dot posts that map we're spreading state at post state at post set map and status post that filter these are going to be all the changes that we have to do with redux it is sometimes confusing i completely understand that but it's going to help us in the long run by maintaining one state of truth that said we can now actually start using the is loading state we can start in the posts.js file so we can open up our components and go to posts post.js inside of here from the use selector we're also going to grab that state is loading and now based on that state we can show some data so we're going to replace this for if is loading in that case we want to show our circular progress which is that loading state and we also want to add one if statement and say if there are no posts that length meaning if there are no posts in the array and if we're not loading in that case we want to return something that says no post because if we don't have any posts and we are not currently loading that means we're not gonna load them they don't exist great so let's save that and see it in action i'm gonna reload the page and take a look at that we have this nice loading state at the top left of course you can style it a bit more make it big and make it in the center of the whole post but it's fine enough we see it on the top right corner now take a look what happens when i paginate it simply tells the user hey i'm doing something wait a second and it's so nice to have that visual feedback it makes your app look so much more professional same thing happens if you search something like the here and also same thing happens if we go for tags like asia there we go we have nice loading and only then do we see our posts and as you can see it works with searching the titles searching the tags doing the pagination or simply getting all the posts that's why i like using redux when you want to have one source of truth of course you could have used context as well and if that's your preference feel free to refactor this application from redux to using context we can go to the home component and right in here you should see that this is the place where we are rendering our pagination and the paper wrapping it first things first i don't always want to display the pagination i only want to display it if we are viewing the content by pages but if you're doing the search i'm going to assume that the user doesn't have a lot of posts to search from like 10 20 or 30. in that way we don't need to paginate so what we can do is we can wrap this into a dynamic block and say if we don't currently have a search query and if we don't have any tags so we can do tags.length in that case we want to show our pagination so one more time let me just put this in here if we don't have a search query and if we don't have tags in that case i want to render the pagination if we have the search or the tags in that case we don't want to render the pagination now that we have that we can also add the class name here and that's going to be classes dot pagination let's save that and see it in action there we go as soon as i save that you can see it looks just a bit better it is displayed right there let's try to sign in to see how does it look like with the form there we go looks extremely good there we go it looks extremely good i also see that we don't have this shadow on the form so let's add it as well right there i'm gonna search for creating a memory right in here search creating a memory and there i can see that that is in the form file so i can just add the elevation equal to 6 to this specific paper if i go back you can see that even the form now has the shadow and all the elements on the page have shadow to make them pop up from the background our pagination is working our search is working our design is good what else do we have to do well of course we have to implement the dynamic memory details page when you click on the memory we want to display everything about that memory in a nice view so let's do that right now to implement the memory details page we first have to see what's going to happen when we click on a specific post to figure that out we're going to go to posts and then post right in here that's not post details it's just the post component so we have to make something happen once we click on this card and the thing we're going to do is we're going to import one more thing from material ui which is going to be the button base and just below this card we're going to add a button base component we're going to give it a class name which is equal to classes dot card action and it's also going to have the on click property on click what do we want to do well we want to open the post we don't have a lot of props so i'm going to put them in one line and finally the ending tag of this has to go below the card content so i'm going to copy it and put it just below the card content but still above the card actions great open post is not defined so let's define it const open post is going to be equal to to an arrow function for now so how is this open post gonna work well it's going to be incredibly simple the only thing we want to do is we want to navigate to a specific url so to do that we have to import use history from react router dom import use history and that's going to be from react router dom we already learned that we have to call it as a hook which is going to be const history is equal to use history and then finally inside of the open post we can simply say history dot push and then we're going to push 2 forward slash posts forward slash and then post dot underscore id so you're pushing to the id of the post that is currently selected and everything else is going to be done for us in that post details page so we know that if we go to forward slash post forward slash id if we go to our app you can see posts id belongs to the post details page so everything else will have to be done in here and in redux actions this is going to be a fairly large component so let's start right away we first want to import react and we also want to import the use effect from react then we want to import a few things from material ui and those things are going to be paper typography we also want to have the circular progress for loading and finally the divider and this is going to be imported from add material ui for slash core then we also want to import a few things from react redux and that's going to be the use dispatch as well as the use selector to get the data about the post as i said these are coming from react dash redux then we want to import moment from moment moment is a js library that deals with time and finally we want to import a few things from react router dom those things are use params and also use history from react router dom great we also have some styles so we can say import use styles and that's going to be from dot slash styles as you can see we don't yet have that file so let's create a new file styles dot js and as always i'm going to provide you with all the styles you can simply copy and paste them right in here they're going to be down in the description while they're scrolling to the description make sure to leave a like and leave a comment for the youtube algorithm now that we have the hooks for dispatch selector params history use styles let's declare all of those hooks at the top first we're going to get the data about the post from u selector that's going to be const post posts and is loading and that's going to be coming from use selector and there we have a callback function with a state and finally we want to get the state dot posts reducer then we want to say cons dispatch is going to be equal to use dispatch we also want to get the history so we're going to say cons history is going to be equal to use history we also want to get the classes so cons classes is going to be equal to use styles and finally we also want to get that id so we're going to say const the structure the id and that's coming from use params remember our url we're going to forward slash posts forward slash an id great we've prepared everything to start creating the jsx layout of our post details component considering that the post details component is incredibly similar to the post component it's going to be a card or a paper that's going to have some typography where we display all of the post details because of that i'm going to give you the jsx code for some parts of our post details component i'm going to paste it in here you're going to find this in the description down below the only thing that's not in here is the most important one and that is the logic for the recommended posts we're going to code that together but before we do that we have to create the data for getting a single post if you remember correctly so far we've only worked with posts plural now we have to create the logic for fetching only a single post based on the id so let's start with that we first of course have to dispatch some actions we're going to do it inside of the use effect and that use effect is going to happen whenever the id of the post changes right inside of there we can dispatch an action and the action we're going to dispatch is going to be called get post action of course we want to get the post by some specific id so we can pass that id in there as you can see our get post id is not yet defined so let's import it we can say import get post and that is going to be coming from dot dot slash dot slash actions forward slash posts now is the time that we create this action and make an api to the back end that's going to serve us all the details about our specific post let's go to our posts and more specifically actions right inside of here we're going to create one more action creator and we can actually do that by copying the get posts i'm going to paste it at the top and there are a few changes we have to make first of all it's not going to be get posts it's going to be get post second thing is that we'll be getting an id as a parameter and that id is the thing we'll pass into our api call then the actual api call is not going to be done to fetch posts rather it's going to be to fetch post and finally our type is not going to be fetch all it's simply going to be fetch post so let's go to our constants and then right inside of here we can create a fetch post action constant great going back now we can import it fetch post and now everything is ready besides the actual api endpoint so let's go to our api index.js and then inside of here we'll have to create the fetch post that's going to be export const fetch post as we discussed we're getting the id as a parameter and then we have to call the api dot get and we have to navigate to forward slash posts and then forward slash id now everything is ready and we have to go back to our backend side and bring us the data so let's go to our server more specifically routes and then posts inside of here we have to create a route for getting a single post we can do that right in here router dot get and the route is going to be 2 forward slash column id this means that it's going to be a dynamic id and what controller do we want to call well we want to call the get post controller of course we need to import it at the top get post and finally we have to create it under posts controllers if we scroll down you'll notice that we already have a good get post controller we created this in one of the previous parts and we never actually used it but now is a good time to do so let's see if everything seems right we're doing the const id from wreck params and we're trying to find that post by id and finally we have res res.status 200 and we're sending that post back that seems all right to me with that said let's go back to our front-end side to our actions now we know that we are getting that post back right here as the data and we are sending it as the payload to our reducers so let's go to our reducers post we have to import that action type which is going to be fetch post our fetch post is going to be similar to fetch by search so we can copy it the only thing we have to change of course is the case it's going to be fetch post and then in here instead of setting the posts to be action.payload in this case we're getting a single post so we're going to set it right in here post is equal to action.payload i know that we've written a lot of code without actually seeing what's happening but we've been dealing with data mostly now we're going back to our post details and see now we have this post right in here if it says right there that we don't have get posts make sure to close the file and then reopen it and it's going to be all good looks like our posts are not currently rendering let's open up the console and it says that we have failed to get a connection there is a network error so let's go back to our code and open up the console as you can see here it says identifier get post has already been declared and the error is in routes post js line three and indeed you might have noticed it but we are already importing the get post here and here so we don't have to do it twice i'm gonna save that and now we're gonna go back to post details component let's go back to the browser and see if it works okay our posts are loading right now and take a look at that if you hover over them you can click them so let's try by clicking one memory and see what happens okay there is an error it says cannot read property title of undefined this usually means that we were trying to render something before the data was actually fetched so if we go back into our post details we just have to add some checks well first of all we're going to say if there is no post then return null and then second of all we're going to add the loading state so if it is loading in that case we want to return a paper component that paper is going to have the elevation equal to 6 and it's also going to have a class name equal to classes dot loading paper and finally inside of that we want to have the circular progress component it's going to be quite a big one so i'm going to set the size to be equal to 7 em we're going to save that and now these two checks are making sure that we don't try to render this jsx where we depend on the post if we don't have the post already if we now save this and go back to the browser you can see that our post opens up it has a nice title we're listing the tags right there description who created the post and when the post was created i also added some paragraphs here to let you know that real time chat and comments could be coming soon let me know which one you'd like to see first i would really like to create the fifth part of the series if there is a lot of demand for it from you guys with that said let's check out our loading states if i now go back you can see there is loading right there and if i click on one of these specific memories you can see this nice loading at the center but we can see it for less than half a second that's because i have a really quick internet connection but what would happen if somebody is running this with a slow internet connection well we can actually check that out and that's one more trick i want to show you you can open up your developer tools go to the network tab and then there you'll see the no throttling thing you want to switch that to fast 3g now this is going to emulate a slower internet connection so let's go to memories and see how nice it is to have a visual representation that something is loading there we go our posts are there and let's try to load a specific memory this loading looked really good now let's bring this back to no throttling and let's close it and let's for a moment admire this nice memory details component and the proc hassle once we're done with that we can focus on the most important part of our memory details component and that is the recommended posts section let's code that out together right now let's code out the recommended posts part i'm going to close all the tabs besides the post details which we're going to have open right here and i'm going to collapse it and close the file explorer just so we have more space to work with the interesting thing about the recommended posts is that we're gonna use the same endpoint we created before get posts by search so i'm going to create one more use effect here and yes you can have multiple use effects per functional component inside of there we're going to have a dependency array that's going to have the post so whenever the id changes the post changes and then we want to do something for each post we want to see if the post exists and if it does we want to dispatch a new action creator that action creator is not going to be get post anymore it is going to be get posts by search the one we created before so we can say right here dispatch get post by search and finally we have to provide that search query in there so we can say something like search is going to be equal to none because we're not looking for search we're looking only for tags that's what we're going to use to recommend the posts so we can say tags is equal to post question mark dot tags dot join and we want to join it by a comma now if we save that this is going to populate the posts at the top finally we can use those posts to create a list of recommended posts const recommended posts is going to be equal to posts dot filter inside of there we want to get our specific post but more specifically we want to destructure the underscore id from there and then we want to keep all the posts but delete the one where the underscore id is equal to the current pose that underscore id of course the current post cannot be in its own recommended posts that's why we are doing this so in here we can say if we have recommended posts so if recommended posts that length if that is the case then we want to display something that something we want to display is going to be a div with a class name equal to classes dot section inside of that div we're going to have a typography and that typography is going to have a gutter bottom to give it some margin at the bottom it's going to have the variant of h5 and then inside of there we can say you might also like finally below that we're gonna have a divider and below that divider we're gonna have a div and that div is going to have a class name equal to classes dot recommended posts inside of that div we want to open a dynamic block and we want to map over the recommended posts by doing recommended posts dot map inside of that div we want to open a dynamic block and say recommended posts dot map so we want to get a post in there and we can immediately destructure all the things we need from the post like title we also need a message we need a name the number of likes and the selected file as well as the underscore id now with all of those things we want to return something so we just use a pair of parentheses and the thing we want to return is going to be another div now let's see how this is going to look like if we just try to render out the title i'm going to save it and let's go to a specific memory details and if we scroll down we can see you might also like this let's see if we have something different in here it only gives us the pose that we're currently on which is not a good thing we need to get all the other posts so i might have made a logical mistake in here we need to have a not equal to because we want to filter out only the one that is equal to and we want to keep all the other ones so now if we go back as you can see now we get all the posts that have something to do with europe that's good but let's make them into a nicely styled cards this div is going to have a style property inside of there we're going to have an object with a margin of 20 pixels and we're also going to give it a cursor which is equal to pointer that means that it's going to show a pointer once we hover over it finally we need to have an on click function what's going to happen once we click it and on click we simply want to open up the post so i'm going to put a callback function right here and we want to call the open post function and pass it the underscore id of the current post finally we also need to specify a key and the key is going to be underscore id of course we don't yet have this open post function but we're going to create it right now so let's go to the top and let's create it const open post is going to be equal to we're getting in the id and what do we want to do with that specific id well we simply want to push to it so we can use the history dot push and we want to push to forward slash posts forward slash and then to that specific dynamic id i see the id is being used currently so i'm gonna use the underscore id here as well now if we save that let's see if that's gonna work we're currently on dubrovnik we can see that we added some margin and let's go to for example the colosseum that's great it gives you the feeling that you can browse through the page and see all the different things that are available great now let's style those cards a bit more and show some more details with each one of them instead of displaying simply the title we're going to display a typography component that typography is going to have gutter bottom it's also going to have variant equal to h6 and in there we're simply going to render our title now i'm going to copy this one four more times or rather three more times the first one is going to be h6 because it's the title and the second one is going to be of a variant subtitle two and it's going to render our name then we're going to have the message below and message is also going to be subtitle 2 and finally we're gonna have the last one which is the likes and that's going to be subtitle 1 and we can just add in front of it likes is equal to and then we can say likes dot length and let's not forget about the most important part and that is the image so we can add a self-closing image tag right here the image is going to have the source equal to selected file and it's also going to have the width equal to 200 pixels if i now save this let's take a look in the browser that looks so much better as you can see we can see all of the posts recommended right there that have something to do with europe but let's go back and let's see if we go to niagara falls if we can see some different recommended posts now we have the statue of liberty and grand canyon let's check out the statue of liberty looks great we can see all the info the image on the right and we have the idea that we can actually navigate through the page with recommended posts being done our whole memory details page is done as well with all of the changes that they've made there are also some things that are not working right now because of the way how we structure the data in our redux for example before as you know the posts were simply an array of posts but right now we're getting an object where then we have the array of posts so there are a few places where we have to fix that one of those places is going to be the form formjs component and then just at the top see here state dot post dot find in this case it's going to be state dot posts and one more time dot posts so we can find a specific post now let's go back to our app and let's see if all the functionality still works let's search for something like let's do sydney that works let's search for something like let's do usa that works as well let's see if the pagination works it works perfectly that is always great and let's try to sign in to see what else can we do i've just signed in let's see if we can like the post we can so that's good there we go we liked a few posts the liking functionality still works let's try creating a new memory let's go with test test test and i'm going to add a file the file is there and if we click submit it's just going to stand there we have to use history.push to navigate it to that newly created memory detail we can do that by going to form finding where we are actually creating that post and then just after that this patch we want to use history dot push um it's going to be pushed like this and looks like we are not importing it so just at the top we have to import use history from react router dom and you know the drill we have to say cons history is equal to use history and finally history.push forward slash posts where are we going to get the id well we cannot get it in here we have to get it just after we created this specific post so what we can do is remove this and not call the history.push here rather pass one more parameter to the create post action reducer we're passing the history object we can go into our action creator accept that history object and then after the post is created what we can do is we can say history dot push and then in here we can use data dot underscore id that's going to re-navigate it for us let's save everything and let's create one more post test test test and i've added the image i'm going to click submit and there we go we are immediately re-navigated to a newly created post and if we go back you can see it right in here at this point everything seems to be working great and the last thing that we have to do to make this a complete project is to deploy it on the internet so you can share it with your potential employers and friends so let's do that right away to deploy the back inside of our application we're going to use heroku when you log in you should see something similar to this at the top right you can see a new button where you can create a new app we can choose the app name i'm going to use something really random like mern memories js mastery that should be available and you can choose your region and then in here you'll get all the instructions of how you can deploy your application using the heroku cli the first thing you have to do is download and install the heroku cli for your own operating system after you do that you can follow my steps before we start writing the commands we just have to make sure to change just a few things in the code first of all go to the package.json off the server side and then in there change this from nodemon to simplynode when you run a server you don't have to constantly restart it so we're only gonna need node and then the second thing is if you don't already have it make sure to rename this to dot proc file we need to have the dot proc file where we say web is equal to npm run start great and the last thing just so we know if our server is running we can go to our index.js and then in there we can create the app.getroute app.get it's going to be just slash and then in there we can get the rec and the res and we can do something like res.send app is running this is just the message that we're going to get in the browser so that we know that their server is running okay with those changes ready i'm going to close these files and let's follow the process run the heroku login press any key that's going to prompt you to log in after you're logged in make sure to run heroku git clone and make sure that you are in the server directory so you need to be in the server directory the process for you might be just a bit different but just follow the steps you need to be in the server folder run the heroku remote to add and finally we need to push all of our changes by running git add we can also do a git commit and finally git bush heroku master this is going to deploy all the changes so that your server is going to be live and deployed on the internet okay we got a confirmation message verifying done we can clear the terminal and expand our browser a bit now if i unzoom this a bit on the top right side you should see open app once you click that at the top left you should see app is running that means that we are ready to take this url and connect our frontend to it so copy that url let's go back to our code this time to the client side we're going to go to the client source api index.js and then in here you're going to replace this base url with your own new deployed server url that is one thing that we have to do and the second thing is that you have to go to the public folder and then in here you have to add one special file for deployment we'll be using something known as netlify and for netlify to work with react router applications we have to add the underscore redirects file so just underscore redirect then you can put forward slash and then the asterisk finally forward slash index.html and finally 200. this is the only thing you have to have in this file once you do that you can close everything and we're now going to cd back into the root and then finally cd into the client side when you're in the client side we want to build out our entire react application by running npm run build while that is building we can expand this and check out netlify we're going to use netlify to deploy the frontend part of our application make sure to log in and then there click sites if you scroll down you should see a place where you can drag and drop your folder so if we go back you can see that the build is successfully finished and in the client folder you should see a new folder called build you can right click it and click reveal in file explorer and finally the only thing you have to do is to drag and drop the build folder not the entire client folder where our code is just the build folder once you do that our app is going to be deployed in a matter of seconds there we go it's deployed before we check it out let's change the domain settings by going to site settings change site name and then in here you can give it your own name let's do mern memories js mastery test just like that feel free to personalize this i'm going to click save and let's go to that url to check it out our memories are loading and we can see the posts which means that our frontend is not only hosted online but also connected to our back end which is also hosted online this works perfectly we can paginate we can see all of the great features that we just created in this video it's so good seeing the application you've been working on for quite some time now being almost done of course there are always some new features that you can keep adding to your applications and keep improving them that was it for this video if it was helpful definitely feel free to leave a like and comment and if you'd like to build more projects with me make sure to subscribe and turn on the bell notifications if you turn on the bell notifications you can be sure that you're not going to miss the fifth part of the mirn series when i upload it if your app is not behaving as it should just feel free to go to this github repo it's going to be linked in the description go to the part 4 and then download it it should be working if it is working and if you like the project definitely make sure to leave a star with that said thank you so much for watching see you in the next one and have a wonderful day you
Info
Channel: JavaScript Mastery
Views: 100,015
Rating: undefined out of 5
Keywords: mern stack, mern stack tutorial, mongodb tutorial, react full stack, full stack, mern stack project, web development, react js, mern stack tutorial 2020, mern tutorial, node.js tutorial, react and node, mern stack crash course, react node express mongodb, mern stack traversy, mern stack full project, mern stack 2020, mern stack tutorial for beginners, mern stack tutorial step by step, mern application, mern app, full stack mern application, mern application example
Id: LYWgPSbPDfQ
Channel Id: undefined
Length: 117min 42sec (7062 seconds)
Published: Sun May 16 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.