Todo List React - React Projects for Beginners

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello and welcome back to the channel in this video we will build together to do mvc project by using react hooks and it might sound like a small project but we will make it really scalable and reusable so let's jump right into it [Music] so here i opened to do mvc website and if you don't know what is it it is a project that is implemented in different languages for example here you can see a lot of different frameworks and for example we have here react as you can see on the right this is how our project will work so we have here an input we can type something hit enter and here is our first to do now we can create one more to do we can also toggle or untoggle all to do's we see the number of items on the bottom if we check something we can jump to active items or completed items and of course all items also we have here inline edition and remove button so actually there is quite a lot of functionality to implement the first step to start this project is to generate it and for this we will use create react app and if you don't know what it is i already made a video on that so i will link it here on the top so as you can see here i open github com create react app and for us important part here is what node version do we need and as you can see here we need at least no 10 version so on your machine you must install node for example from the official website as you can see here we have two versions 14 and 15 and i always recommend to use lts version because it is more stable so you just download it and install on your machine if you don't have it then in the console you can just write node minus version as you can see i have already installed 14th version so if node minus version gives you some output like this and it is bigger than 10 then you are good to go now the interesting part is how we can generate our create react app and if we will check here inside github facebook create react app there are a lot of possibilities for example with using npx or npm or yarn you are getting npm out of the box together with node this is why it makes sense to use it i will use for me yarn just because i have installed it on my machine and i prefer it more but actually the output is completely the same so the idea is that we have something that is called initializer so for example for npm and yarn this is react app so this is the skeleton of our project that will be generated for this i will copy this line completely and jump to the console but here is the small difference between your project and my folder here as you can see i already generated the project so i have a folder monster lessons academy and inside i don't have anything except of git so it is empty but for you you didn't create a project yet this is why you must use this command and inside folder where you will run it it will generate for you my app folder i don't want this approach i want to generate a project inside already created folder this is why i will use this command yarn create track tab but here instead of my app i will just say dot and this dot means that i want to generate create react tab in current folder and if you don't have a folder then you can use the default version where you are setting the name for example i think for us to do mvc name is really convenient after hitting enter as you can see react installs all our dependencies and generates the project for us now as you can see everything is finished and we're getting message happy hacking and done which means we can start to use this project now we need to start our web server so i will jump to another tab and call yarnstart and this will start our create react app as you can see i am now in localhost 3000 and this is how create react tab is looking like now let's clean it a little bit so i will open here our files this is normal create react app and i want to clean it because we don't need all this stuff first of all i will remove here app test js and then app.css and index.css logo report web vitals and setup tests so we just need two files index and app and inside index i will remove vitals and then import report vitals then import index.css and now we just have our plane react start with app component inside now let's jump inside app.js and here we don't need this whole markup so i will remove everything and just write inside hello to do mvc and now we don't need this class so we can also remove it and we don't need this imports on the top let's check this in browser as you can see i'm reloading the page and we can see just hello to the mvc message and our project is ready to be started our next step is to bind our css from to-do mvc project inside drag so the idea is that we will use the whole css that is already prepared for us here into doing vcom this is why here i will jump in our project and create here two new files so i will link this to files in the bottom box below so here i will create to do mvc app css and one more to do mvc base dot css and now here i will paste already prepared css so first of all it will be app as you can see this is really a lot this is like global styles and classes and secondly i will copy here our base so let's jump to base and also paste different classes as you can see we don't want to write everything by ourselves but reduce all these classes inside our components now we need to bind them inside our index.js so here on the top we can import both here is to do app base css and next is import of to do mvc app.css now let's look in browser as you can see it is looking really different so we have different color on the background and different text font here which actually means that we successfully binded this css and we can start doing our application and the first thing that we need to do is of course planning so let's check what we have this is our project and we have here different parts first of all we have here something like header this is where we are typing something and here we can toggle elements secondly we have our main this is where we're rendering elements and we have here footer so here we're rendering the number of items and our filters also maybe we need additional component for single to do here because there is quite a lot of logic first of all we are rendering here we have remove button so remove logic toggle logic and then inline editing so i think we need here four components header main footer and single to do and the next question here how we will store our data and yes this is small project and probably we can just inside app store all our data for example we have here our app component we will store them here and just propagate down from app component but of course this is not the best and not scalable approach much better would be to use create context so actually if you don't know context inside react allow us to share some global things between different components and it doesn't matter at what level they are and this is exactly the idea so we can create something like todo's context and we're storing there the array of to-do's probably our filter and some other methods that we need then everywhere we have access to this context and we can do with data whatever we want so let's start with our app because this is our parent component for everything first of all here i want to write an error function for app because it is looking better and we don't really need to use functions anywhere the second part is that inside here in return we want to render several elements so we will have here header main and footer and for now i just want to create first of all the div this will be our wrapper here is class name to do app and this class is important because it comes from that global styles that we used so here i'm closing our div and inside this div we will have first component header and we will create it in a second so first of all here on the top i want to import our new header component from and here we will have relative path header now let's jump here and create here inside source probably components because we don't want to pollute our global namespace so here i will create components and inside we have header.js and here we can write export default and here will be our header and now let's create here stateless component just for testing so here comes header and we just need to return some markup so here will be return div and inside we can write header so our basic component is ready but here the path is not correct so here i said that this is just header but here now we want components slash header now let's check if it's working so as you can see here our header component was successfully rendered so we have here our shadows and all elements are there now we need to start and create really our header component and the first thing that we have here is of course our input and h1 tag so let's write here correct markup we don't need return div but instead inside return first of all we have our header with class name header now let's close our header and inside we have two things first of all h1 tag and this is our to do's and secondly actually i think to do this with small letter yes here is small t and after this we have our input so here will be input with class name and class name will be new to do and we also need here a placeholder and it will be what needs to be done also we need here value on change and so on but for now i will skip it and just create auto focus because we want by default to focus in this element when we're loading the page so let's check this out we're jumping in our example as you can see it is really similar but it should be a little bit smaller because it is really zoomed so here we have our h1 and here is our autofocused field as you can see after reloading we are directly focusing inside it and we can type something now we need to store somewhere what we typed here so we can use it later when we're hitting enter and for this of course we can use your state hooks from react because we need some kind of state inside our component so here i am importing your state from react and now here inside header we can create text and set text and here we are using your state hook and default value is empty string so this is exactly our state for our input so what we can do here is write our value and it will be our text and we also need here a setter on change so here will be on change event and here let's create a function change text and for this we need to create here on the top this function change text and we're getting here our event and let's for now just console log our event so here will be change text event target value and let's check if it's working so i'm reloading the page we need of course console to debug let's make it bigger and now here i'm typing something and as you can see we're getting this change text console log which means everything is working correctly and now we can use here set text to set our state and inside set text we must provide event dot target dot value so exactly what we read from our input and we don't need our console anymore now we need somehow to trigger our enter so actually we are typing this is fine but when we are hitting enter we need to react for this this is why here i want to add on key down event and here let's create a new event for example key down text and now we need to create this function here so here we will handle our enter click here will be key down text and we're getting inside our event but the problem is here when we will console.log that we are not having it only with enter but with every click so let's check this out here i am reloading the page after each hitting a button we are getting this key down text so actually we need here some logic that we hit it on enter so we can write here if and inside event dot and here we will have key code equals 13 and 13 is our enter then we want to console log our key down text so let's check this i'm reloading i'm typing something we don't have any console log then i'm hitting enter and as you can see we are getting nice console log key down text but i really don't like this code why because here we have a magic number 13 and no developer knows what does it mean of course it is clear key code here and developer can google what is key code 13 but it's not human friendly so what we can do is create at least a variable and put inside 13. but actually if we will use a crossover application a lot of key codes it makes sense to write them in additional file this is why here inside source i will create helpers folder and inside let's create keycodes.js so here we can store all key codes that we need and share them everywhere this is why here will be export const and it will be enter code and here will be 13. so now we know that this is the code of enter button now let's jump back in our components header and on the top import and here will be enter code from and here we will have our helpers slash key codes and let's save this and use instead of 13 here enter code and as you can see this code is much clearer now the second thing that i don't like here is this relative path and this is what we are getting out of the box so relative path are normally not good because first of all i can't really copy paste it because it is relative to some file which means in other component it won't be like this so we really want absolute path because it is easier to read copy paste and replace and to use this we can inside create react tab say how we want to make our absolute path and for this inside our root we must create new file jsconfig.json and inside we want site json so here you have an object then we have compiler options and here our base url is source and we want to include also source directory in this case when we are saving it like this we can jump in source components headers and here use instead of this just helpers dot key codes because in this case this is our root directory source and we can just import everything like absolute pass starting from source so now let's look on our keydown text so here we have our console log and actually we don't want event here but we just need access to our text and text we changed here when we just typed so let's check this out i'm reloading the page no errors here i'm typing something and i'm hitting enter as you can see we are getting key called text and this is our text which means it is working fine but there are several problems first of all we can also have an empty field here and hit enter this of course we don't want to send to our server this is why here we should not allow empty string and secondly if i type something and then i hit it space we want of course to remove spaces on the beginning and at the end first of all here i want to create a const to make our code easier to read so here i want to write is enter and now we copy everything from our if and we name it is enter and here i am just pasting this condition so now our if is better to read secondly we want of course to trim our data this is why here will be new text and here we have our text dot trim so trim will remove spaces from beginning and from the end and the last one is that we need to check if it is empty so here we can name it is text present and here we're checking new text length bigger than 0 and now if it is an enter and is text present then we're doing our console log so at this point we can communicate with our server api or whatever also we want here to change our text to new text because it is streamed now let's check if it's working so i'm reloading the page i'm hitting enter nothing is there now i put several spaces i'm writing full hitting enter and as you can see this is a full screen without any spaces so this is exactly what we wanted our next step is to build a place where we can store all our data and for this we will use react context and of course use context hook so for this i will jump here in source and create new folder which is called context and here we will have all our contacts across the application now let's jump inside and create here new context for example to dos.js and now inside we want to create our first context by using react context so here i want to export const and here will be our to-do's context and to create a context we need to call create context function and as you can see here we are using create context directly from react so actually to this context will be our global context for us where we will store all information about our to-do's or for example filter and inside create context we can provide default value but in our case we don't need to and you will see why in a second so here is our to-do's context this is fine but we also need here a provider this is why here i will create export const and here will be to do's provider so what we want to do here is to have our children and just to remind you we want to prep all our components or part of our components with the provider so we have access to our context everywhere this is why here we need children and these are all our child components and here we will have our todos context dot provider here we can close it and it will be to those context dot provider as you can see we didn't use here children so we need to write it here inside just like children because children is for us our tree of components so our to-dos provider is ready but actually it doesn't do anything so the idea of provider is that we can pass a value inside and here can be string object whatever you want in our case we want here to use use reducer and again what is use reducer this is an additional hook in react that allows us to write the same code like when normally do with redux so what i want to do here is value equals value and we want to create it here now so here we will have value and it will be the result of use reducer and use reducer accepts first of all our reducer and secondly initial state and we don't need the third parameter so actually the idea is that we have several things here first of all we have here context this is what we're using to get data from our provider and in provider we will wrap everything and the most important part here is this value because exactly this value is what we are sharing across all components with the help of the context and we can use here for example string or object or maybe use state to work with state but i highly recommend you to use use reducer just because it is more scalable and we can easily make here a huge object of data the next step here is to create reducer and our initial state so first of all let's create our initial state and you know what we need here so first of all we need here the list of to-do's this is our to-do's that we have and by default it is empty array and secondly it is our filter and by default it is all because if we check in the example here we are loading the page and here we have activated all filter now we need to create here a reducer so here will be our reducer and we are getting here two arguments first of all our state and secondly action and for now we will just return here plain state without any logic so actually this user reducer is already defined correctly here is our reducer our initial state actually here is a typo it is initial state and here we are passing value inside our provider the next step is to wrap all our components with todos provider this is why we exported it here i want to jump inside our app and actually we can even do it inside index.js it doesn't really matter what we need to do is we need to wrap all our components that we want with our new provider and in our case it is to do's provider and here i need to close my to-do provider as you can see this is a simple additional component that we imported from context slash to dos and this is what we just created now because we wrote this line we can for example in our header get full access to the value inside our context this is why let's jump back in components header now here on the bottom we can write for example state comma and here is this page and here what we are using is use context and we must provide inside our to-do's context and just remember it is to do's context not to do provider this is really important because we are passing it inside our use context and now let's console log what we are getting back so here i will write for example context comma state comma dispatch and let's check this out so i'm jumping in our application reloading the page and here what we have first of all this is our object so this is our state that we defined previously inside our context and this page is our function that we can use to change this state so basically everything that we do is we combined use reducer and use context it is really easy and nice to work with our global state in redux approach and use context helps us to isolate this use reducer inside but what is interesting if we will jump into this context here you can see that we are getting the value as a result from use reducer and the result from user reducer is an array with two elements global state and our dispatch method this is why we are passing it inside and now all our components have access to global state and also to this dispatch function this is why here we can see initial state inside our component and use it directly but actually we don't need to use inside header our state and we just need dispatch function this is why for now i will remove the first parameter because we won't use it what we need now to do here is instead of this console or key down text make a dispatch so here we know that we want to create a new to-do because we hit enter this is why here we're calling this page and inside we must provide a type for example add task and we will also provide here payload new text this is our information so here are several words regarding this patch inside this patch we are passing an action this is the part of user user hook and action for us is just an object with type property and this type must be a string it doesn't matter if it's lowercase camelcase whatever you prefer most importantly that this type exists because this is our unique identifier also we can pass other fields inside this section but i highly recommend you to use always the single field payload where inside we are passing some information in this case we are using this page function consistently with the same parameters everywhere so now what we need to do is react on this dispatch and change our reducer so let's remove here console log and jump back in our context all to those so here is our reducer and normally we are writing here switch on action type in this case we can react to different types this is why here we have action dot type and we don't need return state here and first of all we will have here case and our first case is at task and we will do here something for now i will just write return state and actually i forgot round brackets around action type so here it is now we don't have any errors and we also need to add here default and this means that we don't have any case and we just return here our default state now the interesting part is if we will write console log here action and for example let's look on state and action and let's check now it in browser so i'm reloading the page we're getting some error header state is not defined so let's go back in header here on line eight as you can see i cancel locked state but we don't have state anymore so let's remove this console log completely and reload the page as you can see everything is working we're typing something i'm hitting enter and you can see this action so this is exactly our console log here so here we have access to our current state and this is our global state and this is our action as you can see here is type at task and our payload that we want to add in our todos array so now the next question is in what format we want to store all our to-do's so here we have payload and this is for example text but we also want to make some unique identifier for each to do so we need an id and also as you saw in the example here we have two states like is checked or is completed i think is completed is fine and it can be true or false so we need at least to create three properties so what we want here inside a task is to generate our new task this is why here i will write const new task and here will be the object with three fields first of all id i won't write here anything for now then we have our text this is action dot payload and we have property for example is completed and by default it will be false because we just created this new task also i highly recommend you to always put here brackets for the case in this case these properties that we are creating inside like const can be reusable inside other cases in other case you can't really reuse the same variable everywhere inside switch so we successfully created our new task but now the question is what we are passing inside id so it should be some unique identifier and we can generate it for example with math random so we can write here math random and just say to string this is fine for us but we can make it better and take only 16 symbols so this is nice generated id without any additional library and for this i will just paste here math random to string 16. so our new task is there and now instead of return we want to override our new to-do's and the important part of redux or use reducer hook is that we always must return new object this is why here we need to do it correctly so here is my new object and we want to take all properties that we have of the old object this is why we are using here spread and we want to overwrite here field to do's and for this i will spread state dot to dos and merge it with our new task in this case we take all properties from state and overwrite here to do's with the new array now let's check if it's working but again to check it we need inside our header to put back state property from here but just for testing and here let's console log state comma state and check this out so i'm reloading the page as you can see here is our state so to do's empty array filter all we create full and as you can see here we are getting new state to do's and in our case we created a new element so we have an object with id this is our generated id our text that we typed and is completed false so we successfully created new to-do inside our global context now let's remove this state from here because we don't need it and what i don't like is that here we still have our stream it will be really nice to reset it this is why after our dispatch we can just say set text empty string in this case we will directly remove it so i am reloading the page i am typing here something hitting enter and as you can see we have a clean input and actually we implemented everything inside our header component that we need so here we have an input we have here on changing key down and when we're hitting enter we're dispatching at task and we already created it inside our global context the next component that we will implement is our main part and just to remind you here is the example so main part is the list of our edit to do's and we want to write this code in additional components so we can split the logic for example between header and main so for this we need first to jump to fgs and here under header use main and we don't need to provide anything here but we need to import this component so it will be main from components main now let's create this component so inside components here is main.js and for now let's just write export default main and here will be our stateless component so main we don't have any parameters and here i won't return for example just div with text main inside so let's save this and check if it's working as you can see in browser here is our main section so now we need to render here our to-do's now the question is how we can get here to do's and how we can filter them because if we check the example here we're rendering to-do's and when we're changing our filter the list also changes so we need to create a property for example visible to those where we will calculate depending on the filter what to do we need to render and for this first of all i want to open header on the right so we can copy paste some code and actually as you see here we used here use context to get access to our context and this is exactly what i want so here i want to get our state so here we have state and dispatch and here we need to use use context and to pass inside our todos context so exactly like we did previously in our header component now here we can console log our state and so we have access to all properties inside our global state so as you can see when i'm reloading the page here is console.log state and here we have our to-do's and every time when we're hitting enter and we have new to do this array changes so actually we have here access to the array of to-do's and to our filter and now we can write some logic to create new property based on these to-do's and our filter so if here we have filter that is completed then we need to filter here only items which is completed true if here we have active then here should be is completed false and if here filter is all this means that we must return all to do's now let's create this property so here i want to create new property and let's name it visible to those but actually there will be quite a lot of ifs because we need three e's for our three filters this means it makes sense to create additional function so here i want to create a function get visible to those and when we are calling this function we will calculate what to do we need to get back so this is why here get visible to those it is just a function without arguments and here we must write some logic and actually i don't want to have here name state because it's too generic we can say here to do's state and they think it is more clear what we are talking about so first of all here we will have our to-do state filter and here the first case it is active so when our filter is active we want to return here only our active to-do's so what we want to do here is to filter to do state dot to-do's this is our array of to-do's and we can use here filter and here we're getting each to-do and we can write to do is completed and we used here bank so we have negation in this case we will return only non-completed to-do's now the next case is else if our filter equals completed so when it is completed we want here to return only completed to-do's so i will copy this filter and now we have to do is completed should be true in this case we will return only completed to those and the last part is return we can write here else or simply return afterwards here we want to return our to-do state dot to those so here we're returning all to-do's that we have and now let's console log here visible to those to check if it's working so let's reload the page as you can see we don't have any errors here is our list now i'm typing here new element i'm hitting enter and as you can see here we got new element because the filter is all this is why this element is here so our visible to-dos is automatically recalculated every single time when our to-do state changes and this is totally fine for us now let's write markup at least basic to render this list of visible to-do's so here i want to return here we will have section and we won't have any class name for now and inside this section i want to render ul with class name to do list and this will be our list of to-do's and actually i said that later we want to create additional component for every to-do but for now just to see that everything is rendered i will skip this part so what we want to do here is to write a map for our visible to-dos so here is visible to those map we're getting here to do and we want to return our markup and for now we can simply write here lee and here of course we need key it will be to do id this is our unique identifier and inside we want to write to do dot text so this is our markup let's check if it's working and actually i'm adding an item we can see our items here inside main of course markup is broken but this is fine for now we were checking the data is there the next thing that i want to do is hide this main part if we don't have any to-do's actually the idea is that we need to add here additional class on our section so what we want here is we want to write class name and here inside we want to concatenate first of all main this is class name that always there but we want to render here additional class if we don't have any to-do's so here i will write no to-do's class and no to this class is just a variable and we need to calculate it here so let's create it here on the top this is known to those class and here we will return empty string or class hidden if we don't have any to do so here i can write to do state to do's length and if it equals 0 then we want to return class hidden and if not then empty string in our case at the beginning here we will have hidden class and then later it will disappear so let's check we're reloading the page and if we check here our markup so we have here our div to the app and here is main hidden so actually this hidden is this known to those class now i'm creating full for example and as you can see we have here only main and no hidden class so everything is working as expected now i want to implement this toggle all button and actually when we check the example this toggle all is located in header but for some reason it is in the markup of main with position absolute as you can see here we have this toggle all and it is on the top because it is position absolute and here we have top so actually normally it is in main but they moved it to the top yes i think this is not the best approach but as we are using the same css let's implement it also inside main so for this here inside main marker first of all i want to remove console log and secondly before our ul i want to have here input with id and here will be toggle all and we also need here class name toggle all and type is checkbox now here we need checked we don't have it yet and of course on change event we will add it in a second so here is our input with checkbox and here we have label html4 and here we must pass our id of input and it will be toggle all and now inside we will write mark all as completed so here inside label mark all as completed so our input is there let's check if it's working as you can see we don't see this item because our main is not there but now we're typing something and this item appears now now we just need to calculate the value when it is checked and add this change event so first of all here i want to create checked and we need a property for this so it will be ease all to do selected i think this is good name and now we need a change event so on change we want here to create new function on toggle all to do's now let's create first of all this on toggle all to dose function so here on the top i will just create it and write inside console.log so we know that it works so here is our on toggle all to do's and now the question is how we will calculate is all to do selected property actually this is really easy because we have access to our to do state so here let's create is all to do selected and what i want to do is just use to do state to do and here what we want to do is calculate if every element is selected for this we can use every function and here we're getting to do and we need to return our predicate so here it will be is completed in this case if every to do is complete true then here we will get true and we are passing this through inside this checked so let's reload the page as you can see cannot read property every of undefined because here is not to do every but to do's because this is an array as you can see no errors this time we're typing something and we have this checkbox now we're clicking on it and we're getting on toggle all to do's and actually it is not black because we don't have checked to do's so now we need to implement this on toggle all to do's and it also needs to be done inside our to-do's context because this is for us our business logic service so this is why here i will write just dispatching of some action this is why here we have this page and we want to dispatch here with type for example toggle all and here we need a payload and our payload will be event target checked and i think here we need to provide our event so we can read it in this case if this is checked then we want to toggle them all to unchecked and so on so here is our dispatch we don't need console log but now we need to handle this action inside our reducer so let's go back inside context to do's and here we have our switch case so this is the case for add task now we need a new case for our toggle o so here i want to create a property updated to those and we want to loop through all our to-do's this is why here will be state to this map and here we get access to every to-do now what we want to do is merge all properties of our to-do with is completed which will be new and is completed value we are getting from action dot payload so what we are doing here is we are mapping through all our to-do's and we are updating is completed property in every to-do and we are getting back our list of updated to-do's so we need to update them inside the state this is why here i am returning spread of our state and here is our to-do's updated to-do's so we are passing inside todo's new updated array let's check if it's working so i'm reloading the page here i'm typing something and as you can see this is gray now i'm hitting here and as you can see it is black because we changed here our todos array and now all our to-do's are completed if you don't believe me let's console log this so let's jump back in main and here we have our to-do state so we can always console log here our to-do state and check what we have inside so at the beginning it is empty array to-do's now here we have one item to do and this item is completed false now we're clicking toggle all and now we have inside our to-do's one item and this completed is true this is why this check here is black which means everything is working as expected now let's create our footer component so we can change our filter and see the amount of items and here is how it will look like so on the left part we have item left and actually if we have more items then we have board items and not item also here we have three filters all active and completed and we can change between them then the amount of items here is also changed based on the filter so for this let's first implement our new component so in source components we can create new component and name it footer.js and here i want to export default our footer component and we need to create here our stateless component so here we have our footer and this is just an empty component and we can return here for example div with text footer inside so now our plane component is ready and we must import it inside our app so let's jump inside our app and here on the main we can render our footer component and we also need to register it here so we are importing here footer from components slash footer and actually here we can use absolute path and not relative so here i will remove dot and slash and it will work like previously now let's check if it's working so in browser let's reload the page as you can see here is full this is our footer because here i wrote full string now let's think what properties do we need so first of all as you saw in the example here we have the amount of total items that we have so the amount that are active so let's create now here this property but for this of course we need to use use context because we must get access to our to-do's list so here we can write that we need our to-do state and i think dispatch also and now here we are using our used context and we are providing inside our to-dos context as you can see i have here auto import this is why it is already there if you don't have it then don't forget to import both of them so here we have access for our to-do state so now let's create a new property active count and it will be the counter that we will render here on the left so actually active count is just the length of active items so here we can write to do state to do's and what we want to do is we want here to get first of all filter because we want to filter and get only active items so here will be to do not is completed in this case we will get only active items and at the end we can write length because we need to get the amount of them and this is our active item so let's render it in our markup so first of all for our markup we need here footer let's close footer and inside of the footer we want span with class name and here we will have to do count let's close our span here and inside first of all in strong tag we want to render our counter and here we're rendering our active count so let's check if it's working i'm reloading the page i don't have anything now i'm typing something and as you can see here is one now i'm typing once again and here is two so our counter is there but our markup is completely broken so first of all here inside footer we must add two classes first of all footer class and secondly the class which will be hidden when we don't have any elements so hidden class were already created inside main we can write the same code here so let's name it known to those class and here we're doing the same logic so to do state to do's here we're checking lens equals zero when it is zero then we want here to attach hidden class in other case no class and now here in footer we can get a class name and here we want to concatenate strings so first of all class footer and the next will be with dollar no to do's class let's check this out i'm reloading the page now i'm typing something as you can see only after we get the first element we see our footer and as you can see this is a nice markup here with these borders and so on exactly like in the example here but the most important for us that when we're loading the page we don't see footer until we get to those now we need to render our label so actually here on the right we have items left text but we can't really write it just like plain text because when we have only single item we have here item left which means this string should also be calculated this is why let's create here new property and name it for example items left text and what we want to calculate here is the amount of active count so here we have active count and we can use it for our calculation so here i want to write so i am concatenating a string item then here we have a variable actually if active count equals not equals 1 then we want here to add string s in other case we don't get anything here and now space left and actually of course i understand that right in ternary operator inside string is a bad practice but to create a new variable here is a little bit overboth and i think one liner is not that unreadable now let's render this text directly after our strong tag so here we need items left text let's reload our page here and type something as you can see now we have one item left when we have two items two items left so this is exactly correct approach how we need to do it but as you can see we don't have a space between so maybe we need to put here and bsp space and if you don't know what is this this is a space how we're writing it sp inside html because inside html we can't just write space it won't be transpiled but nbsp actually means space so let's reload the page as you can see now it is looking better because here we have a space between text and the number now let's create our filters so actually here after our span with to do count we have the list of filters so here will be ul with class name filters let's close it and inside we will of course have our list so here inside in ul i will create li without any class and inside we will have a graph and actually we won't use it as an a tag we will write the prevent default but we are using here a because the css is writing with a tag this is why here i will write ref slash but we actually won't use it and here inside we can close a and just write all now i will copy this link and here we have text active and the last one will be our text completed so let's check if it's working as you can see we have this text but none of them is highlighted with active class so now we somehow need to highlight them based actually on the active filter and we have our active filter inside our to-do state so just to remind you here is our to-do's here is our initial state and here filter is all and of course we need to change it and we can use this filter from to-do state to understand what link is active here so what i want to do here is create additional function where we will get an active class based on the input so here we can create our get selected class and inside we want to pass our filter name so our filter name will be all or active or completed now what we want to do inside our function is return a filter now inside our get selected class we need to check if this filter name is active so here we need to read filter from to the state this is why to do state filter and we're checking is filter name active if yes then we're returning here class selected if not then empty string and now here inside every a tag we can use this class so here i will write class name and here we will use our function get selected class and we must provide a string inside in this case it will be all now i will copy paste it to the next a and here we have class name but not all but active and the last one will be completed let's check if it's working we're reloading the page and we're typing something and as you can see the first filter is active this is why we have here border and what is really nice here we have this function which actually means that each time when to do state filter changes this function will be automatically called because the component will be rendered and this code will recalculate the active class the next thing that we need to do is implement our click event so actually we want on our ahref add on click event everywhere so what we want to do here is to call a function but here we must use an event because we want to write event prevent default in our function so let's create a function for example change filter and we want to pass inside first of all event and then our string for example all as you can see this is the same stream that we are providing inside get selected class now i will copy this on click in every a graph so here we have also a graph and here is change filter active now i will copy it again and add it to completed part now let's save this and change it to completed so now we have this on click event and we need to create change filter function so let's create it here resconst change filter and we know that we're getting event and our filter name and now let's console log our filter name and do event prevent default so here will be filter name and first of all we need event prevent default now let's check if it's working so i'm reloading the page typing something and i'm hitting another filter as you can see here is filter name active which means now it is time to make a dispatch so we can notify our reducer that our user change the filter and then inside our reducer we can change the state and this will notify all components that are subscribed to this change so here i will remove our console log and use dispatch function so we want to provide here a new type and let's name it for example change filter and inside payload we want to provide our filter name now let's jump inside our context studios and here we can add new case so we have here case and it will be change filter this is exactly what we just created and inside we want to update our property filter this is why here i will just return a new object with spread of state and we want to overwrite our filter with action.payload and action.preload will be our new filter let's check this out i'm reloading the page type in something here i'm clicking on active and as you can see now our filter is active because on click we dispatch new action here is our reducer we have this logic this is why our state was changed and our footer was directly notified because it was rendered so here i can write console log and to do state and you can see that we get a new state after change of reducer so here i'm clicking on active and we're getting again to do state and here filter is active so actually our filter is already there but what is more interesting our visible to do's are also working out of the box because here when i will click toggle all we don't see any items because we are now on the active tab and we don't show completed items now i am jumping to complete it and they can see our item the same with all because we are on all we are seeing all our items so we successfully created our footer component and now it is time to implement the single to do just to remind you here inside main we just rendered this text inside lee but in real example we have quite a lot of logic first of all check in check out then toggle to have editing state and secondly we can hit enter and update this to do and of course we have remove to do and actually i think that this is quite a lot to write inside main because here it is going about main section not about specific to do this is why i highly recommend you to create additional components when you see that you are packing quite a lot of stuff in a single component and here we have our li and actually in this place it makes sense to create new to-do component and we can pass inside first of all this key like we did previously to do dot id and inside we also need to pass our full to-do and here i will close our to-do for now and we don't want here lee anymore because we will use it inside to do component and we also need to import here our new component to do from components slash to do now we just need to create it so let's create here our to do component to and here i will export default our to-do component and here let's create to-do which will be just a stateless component and inside we can return some markup and actually here we know that we are getting the full to-do so i will destruction it like this and inside we can render here to do dot text so let's check if it's working so i'm reloading the page typing something and as you can see it works exactly like previously because here we see this text but it is coming from this to-do component now let's write the correct markup for this component so here i will remove our div and just create li element like we have previously without any classes for now and inside li we want to have div with class name and here class name will be view so this viewpoint is what we see at the beginning so here is the viewpoint now we are double clicking it and we are seeing edit part this is why inside this div view we have first of all input this is our toggler on the left so here we have input class name toggle and we also have here type checkbox and they won't add any values for now the next here we have a label where inside we will have our text so here i am closing the label and rendering inside to do dot text and the last one will be a button to remove our to-do so let's add here a button we will add an event later but here we need a class name destroy for the icon so here i will write destroy and we don't need any text now after this div we will actually have additional logic for editing so here we need property for example is editing and if this to do is editing then we will render some markup and actually this markup will be for editing and we also need to hide this class name view when we're inside editing mode and we will do it in a second so inside editing we want to create an input with class name edit and i will close it for now and here of course not input but input and as you can see we don't have property is editing here so the question is how we will get it and how we'll store it actually there are several possibilities as you can see here in the example when we have two elements and we are activating editing in first of them then we are double clicking on the second element the first is not edited anymore which actually means that we can't really store is editing inside to do because then every to-do can have this is editing true and we will edit several of them simultaneously so we actually can store this property inside our reducer which is completely fine but i want to show you also that this is not mandatory if for example we want to store some data inside main component we can do this this is why in this example we will store the state inside main here and then pass this information inside every to do the question is what information do we need so we can't really store is editing because we need to know what element we're editing now this is why we need to store something like editing id and then calculate if we are editing this component or not so now inside our main ts let's create one more state so what we want here is editing id and we need here of course set editing id and here we're using use state classic react hook and inside we are passing null as a default parameter so by default we don't have editing elements this is why here is now now actually we might put editing id inside every to do and then compare inside editing id with current id but it doesn't make that much sense because to do is stateless and we just care inside if it is editing true or not what we can do here we can write inside a property is editing and this is what we are passing inside to do and inside this is editing we can do a calculation so we can compare our editing id if it equals to our to-do id and this means that this calculation this comparison we have inside main and not inside to do itself and this is much more flexible and correct and also inside we must provide set editing id because when we're double clicking inside we want to call the set editing id from our child this is why here i am passing the whole set editing id inside our to-do now let's jump back inside to do and now we know that here we are getting this property is editing and set editing id and this editing we already used here but set editing id we want to use on double click on this label the problem is here that we can't really just directly call set editing id because we must pass id inside this is why here we can write on double click and i want to create here a new function for example set to do in editing mode and this will be our local function which we will create here so let's create it now and inside i just want to call this set editing id and pass inside to do dot id actually we can write this code inside template but i really like to keep my template as clean as possible now let's check if it's working but for this we really want to write here console.log is editing so we can check if this property is correct so let's reload the page type something as you can see we are getting is editing false now when i am double clicking on this element we are getting is editing true but our markup didn't change but actually if we will inspect this element we will see here on the bottom our input class edit we just don't have correct classes so that we can see our editing and for this here inside li we must provide a new class so here we can create class name and provide here concatenation of several classes and the first of them will be editing class so here edit in class and let's create it somewhere on the top so we need here editing class and it will be editing when property is editing is true so here we will return editing in other case it will be empty string so let's reload the page and check if it's working here we're double clicking and as you can see now we don't see view because it was hidden by css and we're seeing a nice input where we can paste some code the next thing what we're doing with this editing text actually we are typing it now but we didn't change the state so what we want to do is save this thing somewhere in state in our to-do and then when we're hitting enter we want to close it and update our to do this is why we will use exactly the same logic like we did in our header with the input so here let's add first a value property and here i want to write edit text and this edit text will come from our state that we will create in a second so here we want to create use state and by default store inside to do.text and then we can change this property just by changing the state so what i want here is edit text set edit text and here we have our use state from react and our initial state will be to do dot text so by default we just write here inside the value of our to do and now edit text is fine and we also need here change for setup this is why here we need on change property and inside we're passing our change edit text or edit input doesn't really matter so let's copy this change edit input and create here our const and what we want to do inside is change our state this is why here we will have an event and we can read from when the value and write set edit text and inside will be event dot target dot value now let's check if it's working so here i'm reloading the page no errors typing something now we're double clicking and as you can see we directly have the value from our to-do text and now if i will change it i have access through the state for this property everywhere so actually it makes sense now to bind here a key down for enter then we can update how to do when we're hitting enter so for this here i need not only on change but also on key down and i want here new function for example key down edit input let's copy this function and create it here on the top this is our key down and we want here also event so here we can write if event dot key code equals and we have already enter code from our helpers then here we will change to do so let's write here console log change to do and here we need access for our edit text and we also have here our escape this is why here after i can write if event key code and here i want equals escape code and actually we don't have escape code this is why we need to create it in helpers key codes so here i want to export const escape code and it will be 27. as you can see no magic numbers is always good and now i need to copy this escape code and edit here on the top inside imports so here is escape and i will write here console log escape to do let's check if it's working so i'm reloading unexpected use of event so line 14 let's jump there here we have event and of course we named our property not event but just e we can write here event doesn't really matter let's reload the page no errors this time we're typing something here we're double clicking for our edit now i'm hitting enter as you can see we're getting change to do if i'm hitting escape i'm having escape to do which means we successfully checked these two keys and now we need to make a reaction for them so first of all let's cover escape because it is easy we need to restore here a value inside our editing state this is why here we can write set edit text and here will be to do dot text so we are reverting everything back and the second is set editing id we must set it to now because we don't make an editing anymore let's check if it's working i'm reloading the page typing something editing now i really need to have here focus in other case it won't work and i'm hitting here escape as you can see we have the old value and we are not in editing mode anymore now let's implement this change to do part so first of all what we must do here is make our dispatch so we really need a dispatch for our reducer so here we need two things first of all our type it will be changed to do and secondly a payload and inside payload here we must provide an object because we need to provide here several fields and first of all here will be id this is to-do id we must know what id we want to update and secondly here will be text from event dot target dot value so we're reading the value of our input and now we successfully dispatched it but we want to close editing mode this is why after this we need to write set editing id now now let's implement our change of to do inside our reducer so let's jump to context to-do's and here we need one more case and it will be changed to do what we want to do now here is map through all our elements and when we are finding our to-do by id then we want to update it so here i will create updated to-do's and we want our state dot to do's and we're mapping through them here we have access to every to-do and first of all inside we have a check if our to-do dot id equals action.payload.id so this id that we want to change then we do here our magic in other case we're just returning the to-do now what we want to do inside is just update the text this is why here i have a spread and i want to update my to-do and inside i want to update text and text here will be action.playlord.text this is what we passed inside so here we successfully updated our to-do's but we must update the whole state so here i'm merging the whole state with property to do's and here i have our updated to-do's so let's check if it's working i'm reloading the page as you can see this patch is not defined i think we didn't import it here so let's go to the top as you can see here we don't use context at all so we really need here import and we don't need state this is why i am omitting the first parameter we use here only this patch and as always use context and inside we are passing our to-do's context and don't forget that you must import use context and our to-do's context now we have this page and we can check if it's working so here is our to-do i'm double-clicking i'm changing it and i'm hitting enter as you can see our element here is rendered correctly because we updated our reducer which actually means our state and our producing state are in sync with the whole application the next thing that we need to implement is this toggle to do on the left yes we're changing here our checkbox but we need a default value and we also need some styling so first of all let's start with styling actually we need here an additional class so we can highlight that this is completed to do this is why here i'm concatenating several classes and here we will have one more class completed class and now we need here to write this logic so actually we have here completed class and here we want to check if our to do dot is completed is in true so we're checking if it isn't true then we have here completed class if not then just an empty string now when we're loading the page typing something and hitting checkbox actually we didn't change it because here we don't have any state so we need to go inside our input here and use a value and we can read the value directly from to do dot is completed but this is also not enough because this is the default value and by default it is false which actually means we need to change the state this is why here i want on change event and inside our own change i need a new function and let's name it for example toggle to do so let's create now this function somewhere on the top for example here and what we want to do inside is dispatch a new action to toggle our to do so here i will write this page and here we want to create a type for example toggle to do and we need here a payload and inside preload we must provide to-do id so we know what id we must toggle now let's implement this logic inside reducer so i will jump inside context and as you can see here we have changed to do actually our toggle to do is almost the same this is why i will copy paste the whole case and paste it here now we need to rename it to case toggle to do and here we want to update our to-do's and we need to map through them so we are mapping through our to-do's and here we have exactly the same logic but we have this id directly inside action dot preload so here we can remove our id and what we want to do here is change our is completed so here we can write is completed and we just want to inverse it here so we can write to do is completed with the band now let's check if it's working so i'm reloading the page typing something and hitting here check as you can see now it was rendered just because we changed our state because without the change of the state our compound won't be notified that we change something and actually even toggle all is working now because our element is also highlighted now let's implement removing of to do and actually it will be really similar we just need here a new event for our button so here we have this button and we want here a new function so let's create on click and we want here our remove to do and inside this remove to do we want to dispatch something this is why here will be remove to do and actually we can just copy paste this dispatch because it will be the same so we want to dispatch with type remove to do and as a payload we are passing to do id because we want to remove by id now let's jump back inside our context and here create new case so here we will have new case remove to do and inside we want to filter and reject this id this is why here i want to create updated to-do's and we want here state to do's and here we must use filter and we have access for to-do and we want to check that this to-do dot id does not equal our payload so action dot payload if it does not equal this means that we don't need to reject it now we want to return here our state and merge it with our to-do's this is why here i am right into those update to do's let's check if it's working here i am typing something this is our element i am clicking on the cross and we don't see anything because our element was removed if we have two of them for example bar and full we're removing bar here we just see the single element which means it is working correctly and actually we implemented the whole to-do component but there is a one small thing that i don't like when we are double clicking here as you can see we don't have direct focus inside this input and this is not a good ui this is why will be really nice if we will implement it so that when we are setting the edit mode we are focusing directly in this element and for this we must use a reference for the dom element so here what we want to do is create edit input element and here we will store our reference with the help of use ref hook and inside we will pass now because by default it's not there now we need to attach this edit input element for our editing input so here we can write ref edit input element now we have reference of this input and we can use the focus the question is at what point actually every time when we have a render and after this render is edited in property is in true so what i can write here is just before our return use effect and we're triggering here use effect because it will happen after every render and inside this use effect we can write if we have is editing then we do our focus because only after this is true we want to focus on our input so here i want to write edit input element this is our reference dot current don't forget current because we have the reference inside current dot focus and in this case we will focus only after is editing true and we won't do anything when we simply change the state so let's check if it's working i'm reloading the page here is our full element i'm double clicking and as you can see i have direct focus so this is really nice ui so we successfully implemented together our to-do mvc with usage of react hooks and as you can see it was really small project but we made it scalable and we implemented the whole architecture correctly and if this project was too easy for you i have the full advanced react hooks course where we are building the real application from start to the end and it is going 10 hours and if you are interested i will link it down in the description box below so don't forget to check it out and if you like this video and you want more content like this don't forget to put thumbs up to support me and subscribe to the channel and as always happy coding you
Info
Channel: Monsterlessons Academy
Views: 3,378
Rating: undefined out of 5
Keywords: monsterlessons academy, todo list using react hooks, react hooks todo list, todo list react hooks, todo list react app, build a todo app with react hooks, react todo list, react todo list app, react todo app, todo app react, react todo list tutorial, react todo list hooks, react project, react js project, react project tutorial, beginner react js project, beginner react project, todo app react js, react project for beginners
Id: tbot1XH2k5c
Channel Id: undefined
Length: 83min 35sec (5015 seconds)
Published: Sat Apr 24 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.