How To Create A Messaging App With Socket.io And React

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
first i created a zoom clone and in this video i'm going to show you how to create a whatsapp clone and this is going to be by far the largest react project on my channel it's going to have a custom client a custom server hooks context custom components everything is going to be working together to create this amazing clone let's get started now how would you like to have a free ai powered code review tool that tells you exactly what's wrong with your code how to refactor and how to write it better i mean this sounds amazing and luckily for you today's video sponsor in bold is going to give you just that this tool not only gives you your generic linter output but also takes it a step further and uses their ai to give you powerful insight into how to refactor your code to make it cleaner what different metrics your code is following or not following and just general advice on how to write your code in a better way that's going to give you a more maintainable and more bug-free code if that sounds interesting make sure you check out the link down in the description to get started on their incredibly generous free tier and also stick around till the end of this video where i show you how to use in bold on this exact project welcome back to web dev simplified my name is kyle and my job is to simplify the web for you so you can start building your dream project sooner so if that sounds interesting make sure you subscribe to the channel for more videos just like this now before we get jumping into all of the complex code i first want to just show you exactly what the application does because it's fairly complex think about this very similar to whatsapp you have your own personal phone number and you're able to message people based on their own phone numbers so to get started first you either need to enter in your phone number if you've already accessed the app or you just click create a new id and it's going to create a new identity for you let's just do that for all three of these users and we're graded here with our different conversations obviously we have none as well as our contacts which again we have none so let's add a contact you can see down here we have the id of all the users in the bottom corner of the screen so let's just copy this id for this left side one here and we're going to create a new contact on the right side that has that id we're going to give it the name here which is left and let's just create that and we're going to do the same thing down here we're going to copy this contact it's just going to be called bottom right and now what we can do is create a conversation between left and bottom right click create now you can see we're messaging left and bottom right and we can just send them a message say hi this is top right and all we got to do is come over here and click send and you can see that this message populated up here as well as on all the other screens so it says hi this is top right and you can see that on everybody's different screen and you can see their name and since we don't have these contacts added it just has their id so let's add the contact here we can say new contact and this is going to be for top right click create now you can see it says top right here instead and our conversation says it's between this person and top right let's just send a message that says this is left and we're going to just click send and you can see that that's now sent to everybody and you can see that it's populating the name properly and this is what we're going to create in this video so now with all that out of the way let's just close out of all these different browsers and begin working on the code and as you can see i already have a little bit of stuff done i have an empty folder called server where we're going to put all of our node.js server code for managing the communication between our different clients then we have a client folder and all i've done inside this folder is run npx create react app so i just have a boilerplate react app here and if we just change our directory into the client i just click npm start here that's actually going to start up our react application so we can actually see this running and see what we have and as you can see if i just full screen this put it off to the side wait for that to load up it's going to just be a boilerplate react application there we go and for us we don't really need any of this boilerplate stuff we can remove a lot of these different files all these cs and test files let's just get rid of all those service worker we don't need any of that and then inside of our app let's just clear out all these different files we no longer need delete everything in here and just say hello world make sure that's inside of a string whoops there we go and then inside of our index we can get rid of all this service worker stuff down here and now if we save we should see the hello world text being popped up over here and of course we're getting an error saying logo.svg is not available so inside of our app make sure we save this now if we refresh we're getting an error about index.css delete that from here and now finally there we go we have our text hello world being printed out to the screen so we know everything is working now there's a ton of different places we could start with this application from the server to the client but i think the best place to start is that login page just so we can get something easy to look at that's going to be really quick to create so let's in here create a folder called components or say components and inside here let's just move app.js and we're also going to create a new file which we're just going to call login.js and if we just refresh over here and make sure in our index we have everything referenced properly so let's just save that there we go make sure up here we have dot slash components slash app since we moved that file now everything's working again inside of our login component we can just type rfc and hit enter that's going to generate this boilerplate code for us if we go into our extensions here the reason that's working is i have an extension called es7 react redux graphql react native snippets that gives me those nice snippets you can download that if you want or just manually type everything out now inside of our app we're going to be using bootstrap for all of our styling because if we did all the styling manually it would take a long time a lot longer than this video already is going to be so we're going to use boot trap for simplicity so let's just come in here cd into our client and then we just want to npm i react bootstrap and we also want to install just bootstrap itself because we actually need those css files in order to work with bootstrap and speaking of those css files we need to put that inside of our app here and actually instead of putting this in our app i'm actually going to put this in our index.js it just makes a little bit more sense so we can just say import bootstrap and we want to go into the dist folder so we're going to say slash dist css and we want to get a file called bootstrap.min.css this is going to be the minified css file that gives us everything we need to know about bootstrap and if we save immediately we should see now we have bootstrap styles being applied as we get that different font and different margins and padding and everything that's going to allow us to use all these different bootstrap components from that bootstrap library that we installed that react bootstrap so now inside of login here we can actually start making our login form so the first thing that i want to do inside this login form here is i just want to import some stuff from bootstrap we're going to get the container out of here we're going to get that from react dash bootstrap and now instead of having this div wrap everything we're going to have a container so we can just say container close that off get rid of this div down here and now we have a container that we can put all of our text inside of for this login let's just say hello login log in there we go and then in our app instead of rendering out hello world we'll just come in here and render out login and we want to make sure that we import that so we'll say import login from dot slash oops dot slash login now we should see that text hello login show up over here as soon as everything compiles there we go that's exactly what we wanted now the next step is to go into this login and actually do stuff inside of here besides just the text hello login and for this we're going to need a form so i'm just going to import the form component here from react bootstrap and now i'm just going to wrap a form inside of our container so we'll say form close that off we're essentially going to have a group that tells us to enter our id so we can say form dot group this is going to allow us to create a group and inside of this group we're going to need a label so form dot label and this label just says enter your id which have a lowercase like that and then we're also going to need inside of here a control this is essentially our input and we tell it that we want to have a type in our case a type of text is going to be perfect so we'll say type text and then instead of using on change events and value i'm just going to use a ref for handling all of the changes we're going to create an id ref so up here with react we're going to import the use ref hook this in my opinion is just going to be easier for this very simple use case and if you need more information about how refs work make sure to check out my full tutorial on use ref i'll link it in the cards and the description so now we can just say id ref is equal to use ref and essentially this id ref is now going to reference this input control here so we can actually get the value from it when we submit our form another thing that i want to do is i want to make sure that i set this to required and that way we have to enter our input into this id otherwise it won't let us actually submit our page and go forward now if we save let's just see what that looks like you can see we have enter your id and we have the field to enter it so everything's looking good so far but i want to center this in the center of our screen instead of all the way at the top here so for our container let's just set a class name here which is equal to align items center that's going to center our items vertically and we're also going to change this to be flexbox so that way we actually are able to do that but you'll notice when we save it doesn't actually change anything about this to be aligned center so what we need to do instead is set a style here and this style is just going to be a height of 100 vh and that's essentially just going to make it stretch all the way across our screen as you can see here and now you can see that we have our information centered in our screen vertically just like this but the next thing we want to do is make sure we have our input stretch all the way across our screen like it was before so for our form we can just really easily set a class name here of w 100 that's going to give us 100 percent the width and as you can see our form input has now spread out to fill that entire remaining space now we have our actual field for entering it we have our label the next thing to do is actually set up what's going to happen when we submit our form and to submit our form we need to have buttons to do that so let's come down here and we're just going to create a button oops button and this is coming from react to bootstrap so make sure we import that up here my vs code did that automatically for me and inside of this button we're just going to have the text which is going to say login and i want to make sure that i come in here and i set the type of this button to submit so this is the actual button that gets clicked to submit our form just like that now let's just click save you can see we have our login button right here now the next thing i want to do is create another button this one is not going to have a type at all because it's just going to default to the type of button but it is going to have a variant and that variant is going to be secondary it's going to give it a nice gray color and for this one we're just going to say create a new id this is what happens if we don't already have an id that exists so now let's just save and see how that looks you can see we have our two buttons let's just add a little spacing in there so let's say class name is mr2 it's going to give us a little margin on the right hand side of this button and there we go that spaces them out exactly like we want now the next thing that we need to work on is what happens when we actually submit our form we can come in here and say on submit is going to be equal to some function we're just going to call this handle oops handle submit and let's just create that function up above if i can spell properly there we go function handle submit and it's going to take in the event from this and all we want to do is say e dot prevent default this is essentially going to prevent our page from refreshing since when you submit a form it posts to the actual page you're on we don't want that so we're going to prevent that behavior and instead what we actually want to do is we want to call some function for when we create our id and we're going to actually store all of our state for our id inside this app component because it's going to be shared across our entire application so we're going to use the use state hook up here say use state and again if you're not familiar with the use state hook i have an entire video on it i'll link in the cards and description we can just come in here and say const id and set id is going to be equal to use state so now we actually have the state for our id set up we can pass all right actually we don't even need to pass our id in here but we do need to pass in our set id to be set id and instead of calling this set id i'm just going to call this on id submit because this is going to be what happens when we submit our form so now we have an ability to set our id whenever we have our on id submit so now what i can do inside of our login is take in that on id submit that we're passing into it and down here i can call that and i can pass it the value of our id ref so i can see id ref dot current dot value that's going to get the value of this control down here and it's going to pass up to this on id submit function and just to make sure all of this is actually working up here we're going to just come in here and also print out our id so let's just indent that a little bit open up a fragment here we're just going to say id make sure this is indented this is indented and close off our fragment now if we save we enter in an id and click login you'll see our id is being printed out so we know that it's actually setting our id when we click log in if we click log in again you can see it's changing our id as we want and the next thing to focus on is this create a new id button because right now it doesn't do anything but it should create a random id for us so inside of here an easy way to create a random id is by using a library called uuid so we can just npm i'm sorry first cd into our client then we want to npmi uuid and this is going to be a library we can use for creating random ids really easily we can just say inside of here we want to import this from uuid and we want to import something called v4 we're going to rename this to uuid v4 so this shouldn't be from this should be like there we go so we want to take that v4 function we're just renaming it to uuid v4 just so it's easier to work with and now we can create an on click for our button down here so we can say on click is going to be equal to we'll just say create new id and we'll create a function called create new id and what this function is going to do is essentially just going to call that uuidv4function this creates a brand new id for us and we're just going to say on id submit and we're going to pass in that new fake uuid that we just created just brand new random uuid so now if we click create a new id you can see we get a completely random id do it again and again and again and every time we're getting a brand new random id up here now that's pretty much everything for our login page taken care of so we can go back into our app and one thing that i want to emphasize is when we refresh our page you notice that our id gets completely removed we actually want this to persist when we refresh our page when we close our browser and come back to it we want all of that information to persist so we're going to create a custom hook so we'll create a new folder here called hooks and we're going to call this here use local storage dot js and essentially what this is going to do is work exactly the same as use state but we're going to store everything in local storage so that we can come and refresh our page and all of our data is going to stay there so again i'm just going to use that rfc shortcut we don't actually need react but we do need some hooks from here we need to use effect hook and we also need to use state hook to actually store this information and inside of here we're going to take both a key as well as an initial value for our use state so this key is going to be what we store inside of local storage and this initial value is like what you would normally pass to use state in our case with this login we don't really have anything we're passing into it for our id here as you can see it's blank but that's that's perfectly okay so now back to our use local storage here let's get rid of all this return information down here and what we want to do is first get our information into state locally for our application and we need to pull it from local storage so what i like to do when i'm working with local storage is to create some type of key called prefix which is kind of unique to my application so we'll say what's app clone is our prefix and the reason that i do this is that when you have a lot of apps on local host like localhost 3000 for example all of your different local storage is going to conflict with each other so you may have local storage from a different project you're working on conflicting in this project if you just prefix them all you're not going to have that issue it also makes it really easy to find it inside of your you know debug menu exactly which ones are for your own application so now that we have that prefix we have all of our values being passed in let's begin by writing our code the first thing i want to do is get our prefixed key essentially i'm just going to combine our prefix with our key so now we have our string that has our prefix at the beginning of the key we pass in and now i want to use state so we can just say here our value and set value is going to be equal to use state we're going to be using the function version of use state because getting values from local storage and parsing the json is actually pretty slow so we only want to do this once when we run this function so what we want to do is get the json version of our value so we'll say json value equals local storage dot get item and we're going to use that prefixed key just like that now the next thing we want to do is we want to check if we have some data so we'll say if the json value exists then we just want to essentially return our json.parse of json value and actually instead of just doing this i'm going to say if it's not equal to null because in some instances our json value may be zero and then this is going to return false if it's zero when in reality we only want it to return false here when we have null or undefined so now if we have something it's going to just parse that and return it as our default value now if that's not the case we want to first check if the type of our key so if the type of i'm sorry in our key our initial value is a function so it's equal to the string function then that means we're using the function version of our view state and we want to actually just invoke that function so we're going to return invoking that function otherwise we're just passing it a normal default value so we can just return that initial value and right here this is all the code we need to essentially get our value from local storage and actually put it into our state now the next thing to do is actually get our value and save it into local storage and that's where use effect comes in essentially all we want to do instead of our use effect is anytime that our value changes or any time that our key changes so our prefixed key anytime either of these change we essentially need to re-put our value into local storage essentially re-save it overwrite our old value so we can say local storage dot set item we're going to set the prefixed key and all we want to do is take our value and stringify it just like that and now what we can do is return this to work just like set state so we have value and set value and what this is going to do is just return our two set use state values here just like if we used a normal use state but it has all this extra code behind the scenes to persist everything into local storage so now in our app here we can use local storage and make sure that we import that just like this get rid of our use state completely and now when we enter in an id like create a new one for example we have this random id and we refresh and that id persists on our page and that's because if we open up here go to application you can see we have whatsapp clone undefined is stored at that value we don't want this to say undefined though we need to pass in our key which in our case is id so now if i just clear this out create a new id you can see whatsapp clone id now has that value and when we refresh that value sticks around which is exactly what we want now with our login page completely done the next step that i want to work on is what i'm going to call the dashboard it's essentially everything else in our application other than this login page because once you have an id you don't need this login page at all now here instead of printing out our id what i want to do instead is just take the id and i want to determine if we have an id then i want to go to another page and if we don't have an id then i want to do this login page so we'll copy that up here and otherwise i want to go to the dashboard this is going to be a component that we're going to create now and i want to just pass the id into that dashboard we can get rid of these fragments we don't even need these curly braces anymore since we're not in the fragments keep that parenthesis there though just so we can have this on another line and now we can create that new component dashboard.js rfc and we're getting in an id here so all i want to do is just print out that id just to make sure everything's working so we're going to save this save our app and we should see of course we're getting an error we need to import dashboard from dot slash dashboard oops dashboard and now you can see that our id is being printed out and we don't even have the login page anymore because we already have an id as you can see here our id is coming from our local storage so we're just rendering the dashboard page immediately and if we just come in here go to our application and we just clear out our storage refresh you can see we're at the login page we click create a new id and there we go we have that id being rendered it brought us to our dashboard and closed out of the login page now the next step that i want to work on is going to be the sidebar that shows us our contacts our conversations as well as our id and the ability to create new contacts and new conversations is a pretty important part of the application so let's create that sidebar component now just sidebar.js and again use that rfc trick now we have our sidebar this is going to take in our id because it needs to display it to the user so they actually know what id they have so they can share it with their friends essentially this is their phone number so they need to be able to access it now in our dashboard instead of here doing all of this let's just render out our sidebar make sure we import that up here and we just pass in our id just like that so now we're rendering our sidebar inside of our dashboard but our sidebar has nothing we put some text in here and save we should see that text so we know our sidebar is at least rendering and to create this sidebar we're going to use something inside of bootstrap called tabs so from bootstrap we're just going to import here tab whoops tab we're going to import a nav and that's all we need for now so we'll just say that's from react bootstrap there we go so now with all that out of the way all i want to do instead of here is to set up a tab container there we go and actually we need to make sure that this has content inside of it and in order to make sure our tab never takes up the full width of our page we want this to only be a sidebar inside of our div here we're just going to set up a few styles so we'll say style here is going to be a width of 250 pixels that just will prevent it from becoming too wide and we're also going to add a few classes here so we'll say class name is going to be equal to d flex as well as flex column this is going to allow us to easily style some stuff inside of our tab to make sure everything lines up like we want it to so now we have our tab container the next step is going to be creating the nav inside of it so we'll say nav we're going to close this off here and this nav is going to have some items so we'll say nav dot item and each one of these items is going to be a link so we'll say nav dot link and these links all they're going to do is just say for example conversations and let's just copy this down and we're going to have another one here that says contacts and they're also going to have a few additional styles we want them to have a key so we're going to say event key for this one is contacts and event key for this one is going to be equal to conversations this is essentially going to allow us to change between our different tabs by using these event keys and instead of hard coding them like this i really don't like hard coding things like this i'm just going to create some variables so we'll say const conversations key is equal to conversations copy this down to the exact same thing for contacts and this right here is just going to say contacts there we go and now instead of hard coding those in there we're just going to use these nice variables so we can change it all in one place and now we have our different nav links completely done as you can see we have our information up here and in order to make it look like tabs all we need to do in our nav is change the variant to be equal to tabs and we're also just going to set a class name here which is going to be justify content center and that's just going to center our tabs inside of our nav bar here as you can see they're in the dead center if we got rid of this oops got rid of this and save you can see that they're off to the left side i just want them to be completely centered inside of here but right now you'll notice neither of these are active if i click one it'll become active but by default none of them are active so we can do is inside of here set our active key and this active key is going to be equal to some kind of state we create so we're going to create a state called active key let's come in here we'll say const oops active key set active key and that's going to be equal to use state and by default we're going to use conversations as our active key and the reason we're not storing this in local storage is because we don't need to store this information locally it doesn't matter if this gets reset when they refresh the page all we really care about is the main data of like ids and conversations this is really only pertaining to their particular instance of having this open so now if i save oops we're getting an error because we don't have use state installed here so let's import that use state and there we go now you can see that conversations is the default tab that's open but we can't swap tabs anymore that's because we need to set the ability to change tabs so we can just say on select that is going to be equal to that set active key function so now when i click context i can change and i can change back to conversations if i refresh you can see it goes back to that default and the next thing to do then we have our nav done let's just minimize this is to actually work on the content inside of each one of our tabs so we can just say tab dot content sorry content and this is going to be all the information for when we click on our tabs and in order to determine which tab is which we can say tab.pane and we just set an event key so the event key for this one is going to be our conversations key close that off and inside of here we're just going to render our conversations component which we'll create in a little bit we'll just say conversation close that off like this and we'll create a new component for that conversations.js that nice little rfc trick and we'll just say conversations instead of here so we know which component this is save that save this make sure we import that so we'll say import conversations from dot slash conversations and while we're at it let's create our contacts.js component essentially the exact same thing but this will say contacts inside of it so now inside of that sidebar that we are working on we'll just copy this tab pane down but instead of conversations we're going to have contacts and our event key here is going to be our contacts oops contacts key and we need to import contacts so we actually have that component so now if we save you see conversations on this tab and we click over here now we get our contacts tab and we can swap between the two of them now i do want to add a little bit of styling to our tabs just to make them look a little bit better so we'll say class name here is going to be equal to border right and we're going to set the overflow here to auto as well as the flex grow to 1. so what all this does is as you can see we now have this little white sidebar showing up here our little border on the right i'm sorry and what the border right is doing is that the overflow auto means if we have a ton of things inside of here our scroll bar is going to be inside of this container instead of overflowing to our entire page scrolling because we don't want to scroll our entire page to look through our conversations we just want to scroll our sidebar and flexgrow is just going to make it so that this tab is actually growing inside of our container one problem you'll notice though is this is actually not growing as you can see by our border our border should expand all the way down to the bottom of our page if this flex grow is working and the reason this flex grow is not working is because right now the sidebar does not fill our entire height of our page so let's change that we'll create a div here with a class name which is just going to be d flex to make this flex box we're also going to change our style here and this is going to be height it's going to be 100 100 i can type geez 100 vh close that off we're going to wrap our sidebar inside of this now if we save you can see our sidebar is inside this container that takes up 100 of the height so now our flex grow is filling this entire space over here on the left hand side of our screen the reason we added this d flex here is because eventually we're going to have content on the right hand side of our page and it's going to be really easy to style that if we're using flexbox now back into our sidebar we only have a few things left to add the first thing that i want to add is going to be a section that tells us what our id is so we'll say your id and we're going to have a span inside of here that's going to actually say our id like that and we're going to add a little bit of styling we'll say class name here is equal to text muted just so it's kind of this grayish color if we save you'll see our id is down here just got that nice little gray color for our text and also inside of this div let's do a few extra styles we'll say class name is equal to p 2. we're going to say border on the top as well as a border on the right and we're going to change the text to small just so it doesn't stand out too much as you can see it decreased our font size and added those borders to really make this section stand out and the last thing to do is add in a button for creating our new contact as well as our new conversation so let's create our button here and inside of here we're going to have some text it's going to say new and we either need to say conversation or contact and right now we don't really have a good way to do that other than by using this active key so what we can say here is just const contact open is going to be equal to we just want to say i just do conversation open and that's going to be equal to active key and if it's equal to our conversations key that'll be true otherwise conversations open is going to be false so now we can say if our conversations is open we want this to say conversation otherwise we want it to say contact so now if i just save real quick and of course make sure we import button now you can see that we have our new conversation button at the bottom here and we swap over to contacts it says new contact instead so in order to style this a little better though let's just come in here and add some class names for example we'll say rounded oops rounded is going to be zero now you can see we have no rounding around our corners which just makes us fit that space a little better now the final thing yes finally the final thing we need to work on in this sidebar is going to be creating a modal for when we create a new conversation and a new contact so let's import modal up here from bootstrap and outside of our tab container we're going to create a modal and this modal is essentially going to have two modals in it it's going to be either our conversation model for creating a new conversation or our conversion or a conversation modal for creating a new conversation so we can just say here if conversations is open then we're going to do our conversation modal so let's just come in here and say new oops new conversation modal just like that make sure this is self-closing just so it takes up a little bit less space and at the end of that put our colon here and we're going to do the exact same thing but this is going to be for our new contacts model so we'll say new contact modal and of course we haven't created these components yet so let's just create a new conversation modal oops let me just expand this so we can see what we're typing modal.js and the exact same thing new contact modal.js and again rfc on both of these and we'll save them rfc and there we go so now we have both of those modals essentially created that way we just don't get any errors from react as long as we make sure to import our new conversation modal well this is our contact from dot slash new contact modal and the exact same thing here for new conversation modal whoops conversation model and there we go now we essentially have our modals imported and all we need to do is have a show here this is going to be for whether or not true false if our modal is open so we're just going to create a variable called modal open and on hide we're going to create here a closed modal function so we essentially need some state for this again we'll just come up here and say const what would we call it modal open and set modal open is going to be equal to use state and by default this is going to be false because we don't want our modal to be open when we start our application and then also we're going to create a function called close modal and all this is going to do is set modal open to false so now down here we can pass that close model in here we'll also pass it to each one of our modals themselves because we're going to need the ability to close it with an x button inside of each of our modals i'll just copy that put it on both of these and now when we save and we click new conversation you'll notice nothing is actually happening and the reason for that is we haven't hooked up our button to do anything yet so we need to say on click what we want to do is take our modal and we want to set it to be open so we're just going to say here set modal open to true so now if we click down here you can see it opened up our modal obviously there's nothing in it right now though so let's just do our contact modal first if you remember we have a closed modal function being passed into here and in order to use our modal let's just make sure we import modal we want to get that from react and what we can do instead of a return here is return our modal information so first since this is already inside of a modal we're just going to do a fragment and then we want to have our modal dot header this is going to be the top portion of our modal and inside of here we can just say create contact and we also want to make sure that this has a close button so now we're getting an error and it looks like it's because here i didn't put react to bootstrap so now if we save you can see that if we go to contacts and we click new contact you can see it says create contact and it has a close button for us which is exactly what we want now next we can work on the body of our modal so we'll say modal dot body close that off and in here as you guessed we're going to have a form so let's import form and we're of course going to need a button to submit that form so let's just import that while we're at it so let's create the form and we'll say on submit is going to be equal to handle submit which is a function we'll create up here function handle submit and this is going to take in our event oops event and by default we just want to prevent our default and we'll fill in the rest of this function as we get going but we actually need to create the actual fields for our form so we're going to do form dot group and inside of here we're going to have a form dot label and this first label is going to be for our id and it's going to have a control so we'll say form dot control make that self-closing the type for this is text and we're again just going to use refs here so we'll say ref is equal to id ref and it's going to be required we can copy this down paste it again and this is going to be for the name of our new contact and we use a different ref called name ref so now let's come up here get use ref and we just want to say const id ref equals use ref and the exact same thing for our name ref so now if we save we hopefully shouldn't get any errors and if we open up our contact model you can see we have our id field and our name field and we can change these as we see fit and the next thing to do is actually create a button to submit our form that's as simple as just creating a button with the type of submit and we just want to say create in that button now when we click on our new contact you can see we have a create button here obviously this doesn't do anything when we click on it because right now all we're doing is preventing the default and nothing else so inside of here instead what we want to do is we want to call some function for creating our contact we want to pass in our current id value and we want to pass in our current name value just like that and then of course we'll close our modal when we're done because we don't need the modal open anymore but we don't have this create contact function yet so i'm just going to comment this out for now let's just make sure everything else works we click new we type in some information and we click create and you can see it closes the modal for us and if we had the ability to create a contact it would do that as well so now our next logical step is to create this create contact function and instead of creating this function up in the app for example and then passing it down to the dashboard and then we got to pass it into the sidebar and then we have to pass it into this modal here i just i hate doing that instead of what we're going to do is we're going to create a context so let's just create a folder called the context because we're going to have a few in this application we're going to create a new file and this one's just going to be called contact context dot js we actually call it contacts because this is for storing all of our contacts and instead of here we're going to create essentially a custom context and i have an entire video where i show this type of architecture for creating context i'll link it in the cards and description if you're interested but i'll go through it here as well so the first thing we need to do is i'll just do rfc to get our boilerplate react information done we don't want this to be a default export we're just going to make this a normal export and then we also want to make sure in here we have use context being export or imported i'm sorry use context there we go and we just down here need to create our context we'll call it contacts context we're going to set it equal to react dot create context just like that and you'll notice that these names are actually clashing so instead i'm going to change this to contacts provider because this is actually going to be the provider for our context and down here i'm going to change this to contacts provider as well there we go that way we just don't have any name clashes going on and now we can do inside this context provider we're going to take in children since this is going to be a react component that we render so it's going to take in some children and here all i want to do is take our context right here i want to get the provider from it on both the top and the bottom and all i want to do is render out the children inside of it this is just a fancy way for us to easily render out our context provider and the value inside of it which in our case our value here is going to be equal to a object and this object is going to store our contacts as well as a function called create contact which is what we need inside of this new contact model right here this create contact function so how are we going to get this information well it's going to be as simple as actually just creating some state so we can say const contacts set contacts is going to be equal to use and we're going to use local storage this time make sure it's imported up here and this is going to take in our contacts and by default this is just going to be an empty array of contacts since we'll start out with none so now we have our context and the ability to set them so let's create a simple function for creating a contact in this function all it's going to do is take an id and a name and it's going to set our contacts by using our previous contacts and all we want to do is just append this to the end so we can just say return all of our previous contacts spread out and we want to get the id and the name put those into a new contact object and add it to the end of this list so this is creating our contact this is our list of contacts and we have access to both of those inside of this provider now all we have left to do is another export this one is going to be a function called use contacts and this is just going to be a really nice quick shorthand for actually using our contacts so we can say use context whoops context and we're going to pass in our contacts context just like that so now inside of our new contacts modal we can just use this function use contacts so up here let's just make sure we import that so we'll import use contacts from dot dot slash context slash contacts and now here we can say const use oops sorry const and we want to get our contact i'm sorry crate contact function is going to be equal to that use contacts function we're just abstracting that out from our context and again if this seems confusing make sure to check out my video linked in the cards and description for how to do all of this information explained in depth now we can uncomment this here because we have that function created and that's essentially everything that we need but of course we're running into a problem it says user context is not defined so inside of here looks like i just spelled use context wrong let's save and now you can see that that's working properly but we're going to get some problems when we try to create a new contact you can see immediately here cannot destructure property create contact of object and the reason for this is we're not actually providing our context right here we have the using of it we're not using this provider here so in order to do that we need to wrap our dashboard inside of that provider so i'm just going to create a variable here called dashboard and all i want to do is wrap it inside of that contacts provider and then i'm going to render out our dashboard with the id being passed to it just like that and we'll just make this self-closing so it's a little bit shorter and again make sure that we import our contacts provider that's coming from dot dot slash context slash contacts provider and now we can just come down here and render that dashboard variable so now we've wrapped our dashboard in this contacts provider and this contacts provider here has access to both our contacts and the create contact function so now here we can actually create our contacts and it will create it but right now we're not rendering our context to the page so let's make sure that we do that first so inside of our contacts here we just can come in and we can say const contacts is equal to use contacts make sure it gets imported at the top just like that this gives us access to our contacts and now we can loop through them and again we're going to use some handy components from bootstrap so we can just say list group we're going to import that from oops react to bootstrap and now here instead of a div we can use a list group close that off down there and we're going to make this list group variant be equal to flush that's just going to get rid of the side borders on the left and right since we already have our own left and right borders now inside of here let's just loop through our contacts say contacts.map and we have a contact and for each one of these we just want to put them inside of a list group dot item and of course we need to set a key so we're going to set our key here to be contact.id since we shouldn't have any duplicate contacts and then in here we're just going to say contact.name to render out the contact's name and of course we're getting an error it says expecting an assignment or function call and instead saw an expression the reason for that here is i'm not actually returning anything from this function we just change these curly braces here to normal parentheses that'll make it so it returns everything in here and now you can see we're rendering our contacts which we have none so let's create a new one we're just going to give this one an id of 123 and a name of test click create and now you can see we have our contact right here let's create another one we'll say the id is 456. the name is test2 and now we have two separate contacts right here to work with we are finally starting to get somewhere because now if i refresh this our contacts are saved so we have our contacts being stored we have the ability to create new contacts we can log in the only real step left is to be able to create a conversation between our different contacts so let's work on that next it's going to be inside of our conversation modal for this modal we're going to do very similar things to what we did for our new contact model here i'm actually just going to copy a lot of this to start with just so we have a good place to start paste that in and make sure that we import modal and we want to get that from react bootstrap there we go and we also are going to need form so import that as well and a button make sure i spell everything correctly there we go so this is going to say create conversation instead and now we're going to have our form but instead of having our form groups for these different pieces of information instead we're going to loop through our contacts and place them as check boxes so we're going to say context.map we're going to loop through each one of our individual contacts and again we're going to use that parentheses trick just automatically return whatever is inside of here and in order to get our contacts we can use that same context that we created here this contacts provider inside of our conversation modal so we can just import contacts we want to get it from that what is it dot dot slash context slash contacts provider now we have access to all of our different contacts let's just make sure this is capitalized correctly there we go now we're accessing that from this context and now inside it here we can do is create a form dot group and this form group is going to have a control id which is equal to our contact id we're going to do the same thing with our key contact.id and inside of this form group we're going to be using a checkbox so we'll say form.check i'm just going to set this on another line because there's quite a lot of information we need to pass to this the first thing we need to pass is the type in our case we're doing a check box so we'll say check box we also need to say the value of this and the value of this is going to be true or false depending on if we've already selected this current id so we are going to have a list of selected contact ids i'm going to see if that includes our current contact id so we need to create some kind of state to store this information so we'll just come up here const selected contact ids set selected contact ids and that's going to be equal to a new use state and we'll just default this to an empty array let's make sure that we import that use state there we go that way we actually have this information now we have our value being set our label we already know is just going to be the name of our contact so we can just set that equal to contact.name and then lastly what do we want to do when we actually change this so we'll say on change we're going to call a function called handle check box change and we're going to pass it in our contact.id so we know which contact we're working with and again let's create that function up here handle checkbox change and it's going to take in an id we're just going to make sure this is our contact id so now what we want to do inside of here we're going to say set selected contact ids previous selected contact ids and all we want to do is determine if our contact id we have here is already in the list so we'll say if previous selected contact ids.includes contact id so if it already includes it we want to remove it so we're going to return a new list that doesn't have that anymore so we're going to filter out based on our previous id and we're going to check if our previous id is equal to our contact id so we can say here previous id is equal to that most previous id and what this is going to do if we say not equals here is this going to essentially remove every single one i'm sorry it's going to keep all of our ids that are not equal to this contact id and it's going to remove the one equal to that id so essentially it's allowing us to remove it from the list and in order to add it to the list it's as simple as just doing here a simple return if i can spell correctly and we want to take our currently selected ids and add on that new id like that and here i made a mistake this should not be contacts up here this should be use contacts and then we need to get our contacts by actually extracting from that use contacts function just like that so now if we save we're course getting an error it says id is not defined and handle submit is not defined and here this should be previous i i'm not i'm sorry not previous it should be contact id and we have this handle submit function here we never created so let's create that handle submit function it's going to take in an event oops and we want to just make sure we prevent the default of that and at the end we want to close our modal and if you remember correctly we passed that in as the prop here so we'll get that from our props and now just like with our contact we need to create a conversation this conversation is going to be based on our selected contact ids so we're going to import use conversations and we're going to get that from dot dot slash context slash conversations provider and this is going to be very similar to our contacts provider up here so we're going to get that create conversation from our use conversations and now all we need to do is actually create that conversations provider so just like our context provider let's create it we'll create a new file conversations provider.js i'm really just going to copy everything from here and paste it into here because it's going to be very similar we're going to have a conversations context i'm just going to rename some of these we're going to have here conversations so here it's going to be conversations context and this will say conversations provider and this is going to take in our children and instead of here having contacts we're going to have conversations and we're going to have a function for studying those conversations and we'll just make sure we change our key here to conversations so we can store it in our local storage and this function here we can do create conversation and this isn't taking an id and a name instead is taking our recipients essentially so we'll say recipients these are our ids that we selected earlier and now we can set our conversations we're going to get our previous conversations we're going to spread that out here and down here we're going to get all of our recipients and we're going to place these in here and we're also going to default our messages to be an empty array because when you create a new conversation obviously you have no messages yet and now here we can do conversations context on the top and the bottom and here we can pass in our conversations as well as down here we can say create conversation and that should be all the changes we need to make over here let's just refresh and you see we're getting an error cannot resolve component conversations provider so let's just go over to that new conversations modal this should say context just like that let's see if that fixes it there we go it does if we click new conversation we're of course getting an error cannot get create conversation from our used conversations so clearly something's going wrong inside of our conversations provider and let's go over to that and actually the reason for that is that in our app here we're not actually outputting our conversations provider so we want to get our conversations provider make sure we import it up here and do the exact same thing that we did with our contacts provider that should get rid of that error and now we click new conversation you can see we can select our different people up here and we can click create and it'll create it for us but before we do that we need to actually display our conversation so let's just create a conversation between test and test too obviously it's not going to show up yet but it's there for us to know about now in order to make working with our conversations a lot easier what i want to do inside of our conversations provider is actually export a formatted version of this so i can say const formatted conversations like this i'm going to set this equal to our conversations.map and i essentially just want to go through all of our conversations so we'll say conversation and for each one of them i want to format it in a proper way that makes it easier to work with essentially right now all we have are the ids of our contacts being stored inside of our recipients here and i want to also store the name of our recipients so we can say const recipients is equal to conversation dot recipients dot map so now we're mapping over all the recipients for a single conversation and for each one of our recipients this is just an id all we want to do is convert this to an object that has an id and a name so we want to get the contact for that recipient which is just going to be equal to contacts.find and we want to find for an individual contact based on the contact id being equal to the recipient because this recipient is just an id so if these ids match then we will find a contact but first we need to import our contacts so to do that we just say const contacts is equal to use contacts and again make sure that this gets imported up here and of course now we have our contacts and we have access to them make sure i spell that correctly use contacts there we go and now we have our contact so let's get our name our name is just going to be equal to if we have a contact so we'll say contact and contact.name this will return the name if there is a contact otherwise if there's not a contact we just want to get the id which in our case is our recipient then finally with all that done we can return a new object which has the id which is equal to recipient and it has our name property which is either our contact.name or it defaults back to our recipient and now we have our recipients so down here inside of our formatted conversations loop we can just return a new object that has everything about our conversation but we're replacing our recipients with this new formatted version of our recipients that includes the name as well as the id instead of just a list of ids this again will just make it much much easier to work with so now here our conversations is actually going to be set to our formatted conversations and to make this easier we're going to create a variable called output which i'll just create a variable called value so this is going to have conversations which is equal to formatted conversations and we're going to have our create conversation so now here we'll just set this to value it just makes it easier to read well formatted we save and over here so far we don't have any errors so now let's display our conversations that's going to be done inside of our conversations component i'm again doing something very similar to what we did for context so let's just copy this all over paste this in here and we need to make sure we import these components so we're going to need our list group from react to bootstrap whoops react to bootstrap there we go we have our list group being imported inside of here and instead of conversation or instead of contacts we want conversations make sure that's a lowercase and this should say conver station and this here our key we don't actually have a conversation id so instead we're just going to use the index because we know the order of our conversations is not going to change so here instead of the id we're just going to use simply the index and let's make sure we actually get our contacts our conversations i'm sorry so say conversations is equal to use conversations make sure that gets imported up here and there we go now we have access to our conversations we have our conversation and we just need to make sure we actually place our conversation information inside of here so let's just do inside of brackets conversation dot recipients dot map and all we want to do is map all of our different recipients to their name so we can say recipient and all we want to do is get the recipient we'll actually just call this r dot name so if i just change this variable to r this variable r makes it a little bit easier to save on space and we want to join those by a comma and a space so it's going to take all of the names from the recipients that we just created inside of our conversation provider here with this nice mapping and it's just going to display those names in a comma oriented list so if i save you can see but it says test comma test2 if we create a new conversation with just test it'll just say test here so we're showing our different conversations so now we have pretty much our entire sidebar complete we can create conversations we can create contacts we can view them we can do all of that but something we're missing is the ability to select a conversation in order to open it up on the right side of our screen the main side of our screen so let's add that ability here we're going to do that inside of our list item and nice thing about bootstrap is we can really easily make these selectable by putting action on here this is going to make them have styling to be selectable and also we're going to put active we're going to set that equal to conversation whoops conversation i cannot spell conversation.selected we're going to add that inside of our conversation provider here and we're going to have an on click and this on click all it is going to do is just going to take in here a function called select conversation index we're going to pass it the current index of our conversation that we want to select and this function we're going to take from use conversations up here because this used conversations we can easily export a function called select conversation index if i just make sure i spell that correctly select conversation index there we go so now inside of our conversation provider let's do all of that extra work so what we're going to do just scroll up here a little ways we're going to create some state we're going to say const selected conversation index and set selected conver station index it's going to be equal to use state and by default we're just going to select the very first conversation if we have one we'll just use state for this and now we have the ability to select our conversation as well as figure out which one is selected so down here we can just pass our select whoops conversation index that's just going to be equal to set selected conversation index we're just mapping this to a different name to make it easier to work with and now inside of here when we format our conversations let's figure out if it's selected or not we can say const selected is going to be determining if we get our index from up here there we go we're going to just check if our index is equal to the selected conversation index if it's true then it's selected and we can pass that here into our new conversation so now we have our names for our recipients and a true false boolean for if this is selected or not and if we save we're of course getting an error why wouldn't we let's scroll up here get rid of these parentheses don't know why i put that there and now you can see that our selection here is our very first one we can click our second one and now that's selected and just by default when we refresh our page it always is going to be selecting our first conversation if we have one another thing i want to export from here is our current selected conversation so we can say selected conversation is going to be equal to formatted conversations of the actual selected conversation index this is just getting our selected conversation to be used at a later point because we need to display that selected conversation on the right hand side of our screen so now that we have our sidebar 100 percent complete let's work on this right hand side of our screen which is what happens when we select a conversation we're going to create a new com or a new component i'm sorry called open conversation dot js and this is essentially going to be the entire right hand side of our screen our open conversation so now in our dashboard let's make sure we render that out right now we have our sidebar being rendered we also want to render out this open conversation let's just close that off make it self-closing and we only want to render this if we have a currently selected conversation so we can just say const selected conversation is going to be equal to use conversations whoops use conversations make sure that gets imported and now we can just say if selected conversation then we want to render this out so we're just using a nice short circuiting trick to say if we have a selected conversation then render our open conversation so now with that done let's go into this open conversation here and get to work on all this right-hand information which is going to include all of our messages back and forth as well as a form for submitting our own new messages this is going to be quite a bit of involved work so we're going to start down here with the actual styling portion just to get our graphs so the first thing i want to do is make sure this takes up 100 of the width of the screen so an easy way to do that is we just say class name here it's going to be flexbox because we want to be able to change the size of things inside of here we want this to be column because we want our messages to stack on top of our actual text box then we set the flux grow here to one and that's going to make this right hand side fill the full height because it's stuck inside of this dashboard which has display flex so we'll save all that information and we have all this let's just put open convo here just so we can see that this is printing as you can see right here now the next thing that we want to do is going to be a section for our messages and we're not actually going to fill this out completely we're just going to make it essentially a placeholder for now since we don't have any messages we're going to set the flex grow on this to 1 because we want our messages to fill up the most amount of space and we want the overflow to be set to auto because we want it to be able to scroll independently of our entire page if we have thousands of messages we don't want to scroll our page from the very top all the way past all 1000 messages to get all the way down to the scroll bar we just want to scroll this one section so we can get to our input down here much easier that's all i want to do for this section so far because the meat of what we need to work on is our form for actually sending messages before we can display them so of course incomes bootstrap we're going to get form from bootstrap whoops react dash bootstrap and here we're just going to render out a form make sure i spell form properly there we go and inside of this form it's going to be rather simple we really only have one input so we're going to create a form group just like that and inside this form group i'm actually going to create an input group and the reason for this is that i want to have our send button attached to our input so let's just make sure we get import group from here there we go and inside of here i'm going to have our form dot control this is going to be as a text area because we want this to be multi-line possibly if they need to send a message like that we're going to set the required on this and our value is going to be equal to this text state that we're going to create and let's just put all of this on some new lines so it's easier to see oops there we go value close this off we're also going to have an on change on here this on change is just going to be taking in an event and this is just going to call the set text function from our state that we're going to create in a little bit we're going to set the target value and then finally we're going to have some styling in here and all i want to do is set the height oops put this in an object the height is going to be 75 pixels just so it's a little bit bigger and we'll make it so the resize on this is none since we don't want the user actually changing the size of this text box now let's create that state up here and say const text and set text is equal to use state and by default we're going to have this be an empty string and we're going to get use state here from react and if you save you should see that there's actually no error showing up and we have our text box down here which is exactly what we want now in order to space it out so it's not pressed right up against our sidebar let's just take our form group here and add a class of m2 this is just going to give us margin on all sides and as you can see that makes it fit into this space much better and my camera is probably in the way so let me just move my camera over to here for now there we go and the next thing that we want to do is to add in a button so we can do this at the bottom of our input group here this is going to be an input oops input group dot append this is going to add it to the end and we need to make sure we import button so up here make sure we have button in there and then we want to set the type of this to submit and the value is just send so now if we save you can see we have our send button being added on to our text area which is what this input group is used for now the next step is going to be handling the submit of our form so we'll say on submit is equal to handle submit and let's create this function up above function handle submit it's going to take in that event and just like always we want to prevent the default of that now inside of here we needed a call a function called send message which we're actually going to get from our conversations so we're going to say const send message is equal to use conversations make sure it imports at the top just like that and this we're going to create in just a little bit so we're going to send a message and we need to first determine the recipients this message is going to go to so we're going to say selected conversation which we can again pull from here so let's say selected conversation we want to get the recipients recipients and we want to just get the ids so we're going to say recipient and we want to get the id we'll just change this to be r instead of recipient so r and r so now we essentially have whoops our recipients being passed into our send message function the next thing we need to send into this function is the text that we're actually going to send and that text just comes from this state here and then we can set our text to an empty string clearing it out after we send our message so when we send our message down here click send it'll clear everything we sent inside of our text box so we can go ahead and send another message immediately but now we need to create this send message function so let's jump into our conversations provider and work on that function let's come in here and we're just going to create a function called add message to conversation and this is going to take in a few different parameters we're going to have our recipients we're going to have our text as well as the person that actually sent the message the sender and the reason we're creating this function here separate with all these different parameters is because this is actually going to be a message that gets called both from our server when someone sends us a method message as well as when we send a message to other people so we need to make sure this is flexible enough to support taking messages from others as well as taking our own messages and then we can create that send message function which takes in our recipients as well as our text and really all this is going to do is call the add message to conversation it's going to pass in our recipient it's going to pass in our text and the sender is just going to be our own current id and i believe this id we need to pass into here because we don't actually have an id yet so we're going to pass it in as a prop to our conversations provider so inside of our app where we have our conversations provider let's just make sure we take our id and we pass that in as a prop so now inside of here our conversation provider we have access to that id which we can set as our sender when we call add message to conversation then we can take send message down here and we can just export that out with all of our other information inside this value object so now our send message is available for us we just need to actually implement it through this add message to conversation function now this function seems like it should be really straightforward but it's actually a little bit complex because all we have is an array of recipients and we need to figure out what conversation that goes to or if we need to create a brand new conversation since we don't have those recipients yet so let's call the set conversations method and get our previous conversations and the first thing that we need to do is determine if we've actually made any changes so we'll say let made change equal false and the reason for this is so that we can determine if we have a conversation that matches one of the recipients here if we don't have a conversation that matches this will be false and we can add a new conversation at the end so we can just say if made change is equal to false which actually make it here true so we'll say else so essentially if made change is false we didn't have a conversation that matches so we need to add a new one so we'll take our previous conversations we're going to create a new one that has those recipients and the messages instead of being an empty array is just going to be an array that has our new message inside of it so let's create that new message variable whoops new message that's just going to be equal to an object that has our sender as well as our text and we can put this on two separate lines here just like this to make it easier to read so as you can see we're taking all of our current conversations and adding our new one if we didn't make any changes which means that we didn't have any conversations that matched so like i said that was the easy part so now we need to move on to the hard part which is going to be actually modifying this array to include to see if we have a conversation that matches these recipients so we can just create a new variable called a const new conversations we're going to set that equal to our previous conversations.map through each one of our conversations and inside of here we need to check to see if our recipient's array matches the recipient's array of each individual conversation so if we're going to call a function called array equality which we're going to create and this function is just taking two arrays and it's going to see if they're the same so we're going to take our conversation recipients as well as our own recipients and if these are equal what we're going to do inside of here is we're going to say made changes is true and we're also going to just return here a new version of our conversation which spreads out all of our current properties but it's also going to take our messages and add that message to the end again i'm going to put this on a separate line just to make it easier to read so it's going to take our conversation.messages spread all those out and it's going to add in our new message to the very end of it so essentially we're adding that message to the end of our list or we're creating a new conversation with just that message in it so that's all we need to do in this if statement otherwise if that's not true we're just going to return our conversation as is so we don't have to worry about it now with this new conversation down here we can just return that if we did end up making changes so now the last thing to implement is this array equality function i'm just going to do this all the way down here outside of our component because it doesn't depend on anything in our component this is just going to take a and b two different arrays and essentially all we can do is say if a dot oops dot length is not equal to b dot length well immediately we know that this is false they're not equal so we can just return false otherwise we need to sort them both so we'll sort a we're going to sort b and then we're going to just loop through all the elements of a so a dot every element and index we want to check if every element is equal to the element inside of b so if element is equal to b of index essentially this means is every element in a equal to every single element in b at the exact same index position if so our arrays are exactly equal and it doesn't matter about ordering which is why we did this sorting first so now with all that taken care of this hopefully should add a message to a conversation based on recipients we should be able to type down here click send and it should add that message to it let's just make sure we inspect here go to our application and if we check our conversations and make this a little larger you can see inside of our first one we have messages and our message has a sender which is our own id you can see this matches our id down here and also has the text that we typed in so now we can work on displaying our messages and just like we did with recipients down here i want to make a nice human formatted version that is allowing us to easily see the name of the person as well as to determine if we sent this message or if someone else sent it so we can just come down we can say const messages i'm just going to do a little bit of neat spacing here to make this a little easier to read it's going to be equal to conversation.messages.map over each one of our messages and of course spell message correctly there we go now we can get our contact this is essentially exactly the same as what we have up here i'm just going to copy this word for word and instead of here being equal to our recipient we want to check if it's equal to our message dot sender and then down here instead of doing our recipient this is message.sender so now if we have a contact that is equal to our sender we know that as this particular contact otherwise we're going to set the name equal to our message.sender which is just the id of the person that sent it it's our fallback lastly i want to have a from me section and all i'm doing here is checking if i am the one that sent it so if the sender id is equal to my own id i know i sent this so i have this from me flag that's set to true now here i can return all of the message information but i want to take a new property called sender name and i want to set that to the name and i want to get that from me property and also add that to our message so now when we access our messages if we make sure to put this inside of here there we go so now when we actually access our messages we should be able to access the sender name as well as the from made property which originally were not there so now all the way back to our open conversations we can dive into this section which is displaying all of our messages let's minimize this form section and we can come in here create a div this div is actually going to have quite a few classes on it this is like the wrapper for all of our messages so we'll say class name here is h100 we want this section to take up 100 of the height that's remaining in our screen then we can set this to d flex flex column since we want to stack these vertically on top of each other we're going to align our items in the center i'm sorry not the center the start what that's going to do is put all of our messages on the left hand side of our screen and we want to justify our content on the end and what that's going to do is start our messages at the very bottom and they'll work their way upwards and then finally we'll just add a little bit of padding on the left and the right of three just to space it away from our sidebar on the left and the right now we can get inside of this div and actually display our different messages so we can say selected conversation dot messages let's map through each one of those messages along with the index since our messages don't have any form of unique id we can say const and now inside of here we need a return statement and this return statement is going to have a div and this div is going to essentially be our first div that wraps our message so this div is going to be the one that contains our key we're going to put our key as our index since we don't have any unique you know id that we can use for this instead also we're going to set some class names to this we're going to say that our class names is going to be my1 we're going to want d flex on here and flex column again in order to stack these vertically because this is going to wrap our message bubble as well as the name of the person that sends the message this is our wrapper for both of those pieces of content and in order to clarify that a little further let's have our div which has our message dot text right here we're also going to have another div and this one is going to have our message name so we can first check if it's from me because if it's from me we just want to say you and otherwise we want to put the actual name so we'll say message.sender name there we go and we'll put this on a new line just to make it easier to read there we go same thing with up here we'll do a new line for all of these i think it just makes it easier to work with so this is our wrapper around these two different pieces of con of information just like this and this is going to put our message on the left hand side let's add a few more styles to get our message looking really good so we can say here we want rounded px2 that's going to give us a nice round shape that has a little bit of padding on the top and the bottom and here py1 is for top bottom px for left and right and to determine what color we want this to be we're actually going to check our from me variable so instead i'm going to use string interpolation here instead of the normal string because i want to have a essentially inline if statement here i'm going to put this on another line oops there we go so essentially i want to inside of here say if message dot from me is true then i want the background to be our primary color and i want our text to be white otherwise if it's not i just want to have a simple border so no background color at all so it's just going to be a nice white border instead and then for down here our text what we want to do for this is class name i'm again going to do text or i'm sorry string interpolation we want it to be muted so it's kind of this gray color we want it to be small so it doesn't really stick out and then if it's from me what we want to do is just set the text to be on the right hand side otherwise we don't do anything so let's just save that to kind of see what we have and of course we're getting an error saying it cannot get this token this is on the line for our selected conversation up here and the reason for that is that we just have an extra parenthesis here if we remove that and save we're now getting a different error down here and let's just see if our parentheses are lining up it looks like we have an extra bracket and we're missing our parentheses here so now if we save i'm sorry in the wrong order now if we save our extra parentheses here and our extra bracket there there we go so it should go bracket parenthesis bracket now we save we're getting our information and you can see our message is showing up right here but of course it doesn't look like our message from me is working obviously i just typed from here this should be from me that's giving us that nice blue color which is exactly what we want but this message is on the left hand side generally when you're in a messaging app the messages you send are on the right so what we want to do is put it on the right hand side so again that's going to be more of this string interpolation so we can say message dot from me and what i want to do here is a line i'm sorry if align self end and then i just want to come in here with an empty string for the rest and now if i save you can see that it's going to put this all the way on the end which is exactly what i want now if we send a new message you can see that message pops up on our screen and if we send a bunch of messages you're going to start to notice something happens just keep sending these messages and here we go we don't have any way to scroll so clearly there's something wrong with our application right now this is because we have this h100 up here we just remove this and save you can now see that we have this scroll bar but when we type in a new message click send it doesn't scroll us to that message so it stays hidden for all the way up here type new message click send we don't get scrolled down to that message so let's actually go ahead and fix that it's fairly simple to fix actually what we need to do is create a reference that's going to reference our last message so we can say const last message ref is equal to use ref oops use ref and make sure we get that up here use ref we're also going to need to use effect for this so let's just import that while we can so we have our last message ref and then we're going to create a use effect oops and essentially in this use effect all we're going to do is every time our last message ref.current changes we want to actually run this and all we're going to do inside of here is if our last message ref.current so if we have a current message all we want to do is take that message and we want to scroll into the viewport so we'll say scroll into view and we're going to set smooth equal to true so we get a nice smooth scroll so now if we just type in our message click send of course nothing happens we're probably getting an error let's see what that is use effect just pass this penny list that's not an array literal of course this needs to be inside of an array so now let's test this make sure we refresh our page type in a message click send and again we got an error let's check to see what this is on the console oh yeah of course we don't actually need this ref inside of here let's just remove this so this effect will run every single time we render and now what we can do is finally type in a message quick send and again it didn't work of course inspect we have no error this time so there's something else happening and of course obviously we aren't setting this last message ref to anything down here we have our information to determine which one is the last message we're not actually doing anything with it so here we want to set a ref equal to our ref for our last message so we're going to say if this is our last message then we want to set our last message ref otherwise what we want to do is just pass in null because we don't actually want a ref and up here we can say constlast message is equal to selected conversation dot messages dot length minus one is equal to our index so that will be our last message when our index is equal to one minus the length of all of our messages now as you can see immediately it scrolled this down to the very bottom let's just scroll back to the top type something in and you can see it's scrolling us every single time we type and the reason for that is because here our use effect is running every single time but now if we click send you can see it scrolls us down here so what we want to do is just fix this so it doesn't change when our text changes we only want it to be when our last message ref dot current changes so now refresh scroll up to the top type some information now the reason it doesn't work when you just add this last message ref dot current in here like this is because this is constantly changing every single time our component re-renders because it's getting kind of a new reference to that element so instead what we need to do is we need to use a use callback as our ref instead of this used ref up here so let's create that use callback we're going to call it set ref is equal to use callback and this use callback to make sure that we import it all the way up here is actually going to be what sets the ref for us and this use callback is going to take in a node and all we want to do inside of here is say that our last message ref dot current is equal to that node we don't actually even need this ref anymore we can just do here is just say node dot scroll into view we can say smooth is true we can get rid of this last message ref just make sure that this only runs once come down here get rid of this use effect and we can take set ref and set it down here now if we scroll up start typing you'll notice nothing scrolls but as soon as we click send of course we're getting an error scroll into view of null let's come up here to make sure where did i put that at here it is we just want to check if node then we actually run this there we go so now scroll away at the top start typing click send and you can see it scrolls us to the bottom same exact thing send and it scrolls us all the way to the bottom so we can get rid of use ref and use effect because we don't even need them we just have this simple use callback that is going to do this ref for us now with that done we're going to move on to the fun part which is making this work across multiple different clients and to do that we need of course our server so inside of our server let's just go into there we can say cd let's see what folder we want if we say ls we're in that folder so we'll go backwards one and we'll go into our server folder and we'll just type in npm init dash y that's going to give us a default package.json and we need to install inside of here a few dependencies we need socket.io as our first dependency this is going to be for creating that real-time communication between the server and the client and also i'm going to do a dev dependency so we'll say save dev and this is going to be nodemon just to automatically refresh our server when we make changes but our server is going to be relatively small which is going to be nice and let's create that server.js while we're at it and then once this finishes downloading and of course we got an error let's just try to rerun that to see if that fixed it maybe me opening up the file actually caused a problem and of course that's what it was so now we have nodemon installed and we can come in here we can create a script called devstart which is just going to be equal to nodemon of server.js which is that file we just created here and now inside of here let's set up our i o connection so we can get i o which is going to come from socket io and we want to call it and pass in the port we want to use in our case we're just going to use the port 5000 then we can say io.on connection just like that we want to access a socket and this is the socket that we're connecting with and when we connect we're actually going to pass up the id of our user this id right here so we're going to say here const id is going to be equal to socket.handshake.query.id and we'll be able to pass this in from the client and then we can just join that particular room so we're essentially creating our own ids for socket id because we have static ids and socket id creates a new id every time you connect so when we refresh our page we get a new socket id this is just a way for us to have a static id that stays the same every time we refresh our page because if every time that you closed your phone and opened it you add a new phone number it would be a pretty useless phone this allows us to keep that same number consistently now we can do is connect or we can create messages here so socket.on send message so whenever we send a message from the client to someone else it's going to come through this send message here this is going to take in our recipients and it's also going to take in that text we're sending just like when you remember before when we are sending a message inside of that send message function we add our recipients our text and our sender this is going to get the recipients and the text for it then what we need to do is just loop through all of our recipients so we'll say sipping stock for each recipient we need to send them this message but one thing we need to do is actually change the recipients because if i send a message to you the recipient is you but on your end when you send a message to me the recipient is me so we need to make sure we swap out this recipient with essentially the person that's sending the message so a really easy way to do that is to say create a constant variable new recipients is equal to recipient dot filter this is actually recipients sorry this should say filter and all we want to do is just check if r is not equal to the current recipient so what this is doing is removing the current recipient from the list of recipients and then the next thing we want to do is take our new recipients and we want to push in the id and this id is the person sending the message so we're adding the sender to the list of recipients and removing the person receiving the message that way when they get this it'll have the proper list of recipients for them now all we need to do is take our socket we need to broadcast a message which is going to send a message to a particular room in our case the room is going to be our recipient id the only person in that room is the person getting the message so it's essentially sending it to one person we're going to send the message receive message that's the name of it and it's going to essentially have the values of recipients which is going to be our list of new recipients it's going to have a sender which is this current sockets id and it's also going to have the text for the message itself and that's all the information we need to send down to this receive message and this code right here is everything for our server here it's a very simple server so let's save that and make sure we say npm run dev start and now we're going to have that server started up on port 5000 of our local host so now let's go into our client go into our source and open up our context and we're going to create a new one which is going to be our socket whoops provider.js that same rfc trick here and this socket provider again is not going to be a default export and we're going to need our export function for use socket just like all of our others and this is just going to say return use context of a socket provider i'm sorry socket context just like that and let's create that socket context const socket context is equal to react dot create context and we need to get use context from here use context and also we're going to need use effect and we're going to need use state because we're going to be storing state doing something with it and we need that context for this function here now the socket provider is going to take in the children just like all of our other providers but it's also going to take in our id since we need to send that up to our server because it's using that id right here so then inside of here we just say socket context.provider and the value is going to be equal to a variable called socket which we're going to create as our state for this application so we can just say const socket and set socket and we're going to set that equal to use state and by default it's just not going to be anything now in order to get our socket set up first actually we need to make sure we render our children inside of here but now to get our sockets set up we just use an effect because this is going to be a side effect we only ever want to create our socket when we initially load our page or if our id for some reason changes we of course need to create a new socket so here we can create a new socket which is equal to io which we need to pull in a library to access but essentially that's going to be socket io we need to passion our url which in our case is http colon local host and remember that's on port 5000 and then this is the magic we pass in a query and in our case this query is just going to have our id let's just put this on a separate line so it's easier to read there we go i'll put this on the line too so our query is containing that id so that's how we get that query id up here that's coming from this line right here we pass that in when we create our new socket then what we can do is we can set our socket equal to that new socket and most importantly we need to make sure that whenever this use effect runs a second time we need to remove our old socket so we can say new socket dot close this is just going to close our old socket and create a new one that way we don't have multiple socket connections to the server because that's going to cause us to get duplicated messages and that's obviously not good now in order to actually access this i o here which is open up a new tab and a cd into our client and we need to install a library called socket dot io dash client and this is going to be the library we use on the client to access this i o here and we just import that i o from socket.io dash client now once this finishes downloading we're going to have access to this variable here which is this function we can call to create a new socket and now we just want to make sure here we have our socket being returned so anytime we use this socket provider we have access to a socket in our entire application so in our component for our dashboard i'm sorry our app here we're going to wrap this in our socket provider we just need to make sure we pass it our id so it has access to that wrap everything inside of it and there we go we now have another context being wrapped inside of our other ones so now we have access to our socket in all of these different instances and that's really important inside of our conversation context so let's open that up real quick and if you remember correctly we have this send message but we want to make sure we send this message to everyone not just us so this is where we need access to that socket so if we scroll all the way up to the top here we can get that socket which is equal to use socket and make sure again that gets imported up here and now we have access to our socket and we can omit a message this message if you remember coffee is called send message and it's going to take in our recipients and it's going to take in the text just like what we have up here and that's going to send the message to all of our different clients and as you can see it's going to come up to the server oops that's not our server let me open up the server real quick it's going to come up to the server inside of here it's going to loop through the recipients and it's going to emit a message of receive message to each one of our clients so we need to actually handle that receive message inside of here as well we can't just do that inside of our component we can't just say this you know like socket.you know receive message here and the reason for that is that because this gets run over and over and over again and we're going to have tons and tons of references to this receive message so every time we get a message it's going to call hundreds of these different receive message handlers because every single time this component re-renders it's adding a new event listener obviously that's very bad we need to use effect instead so we're going to say use effect make sure i get all the parentheses right in there and let's make sure we import use effect just like that so now if we scroll down to that effect the first thing i want to do is just check if our socket even exists if for some reason our socket is a null all we want to do is just return we don't want to do anything in this function if we don't have a socket if we do though we want to say socket io on receive message what we want to do is we want to call that add message to conversation function because if you remember from our server we're passing down the recipients we're passing down the sender and we're passing down the text which is exactly what that function takes this add message to conversation function and then the next thing that we want to do since we have that set up is we want to set up a return here and all this is going to do is take our socket and we're going to remove that event listener so we don't have multiple of them so we're going to say receive message and we're just removing that event listener completely there we go now we need to set up our dependencies here we're going to depend on socket as well as our add message to conversation function but immediately we have another problem this add message to conversation function all the way up here changes every single time we re-render our component so we need to use callback to make sure that doesn't happen so here we'll just set up use callback instead of having this as a function we're going to have it as a variable we're going to set that variable equal to use callback we're going to wrap this entire thing inside of that use callback so let's just make sure this is set up as an arrow function wrap everything inside there in that use callback and this is essentially depending on certain things and if we scroll up you can see the only thing this function depends on is our set conversations so we'll put that right there so whenever this changes it's going to re-render this function but otherwise this function will never change which means that this use effect won't change due to this which is great because if this changed every time we re-rendered it'd be a lot of unnecessary adding and removing of event listeners and we really don't want that so now i'm just going to create here a new incognito tab and i'm just going to go to that localhost 3000 and this is going to just let us create a new id i'm going to copy this come over to our contacts create a new contact with the id and the name is going to be incog here so now we can communicate with this person by creating a new conversation with them we'll click on incog and we'll just say hi and if i did everything right we should see this on both sides click send and as you can see we see this high message showing up here which is exactly what we want and we have the id over here we can actually copy this id add it to our contacts we'll just say normal click create and now it has everything correct but you'll notice one kind of thing interesting is this box up here is a little bit too wide as you can see it says white is this name down here which really doesn't make sense so let's actually just go into our open conversation down where we're rendering all of our messages and let's fix that essentially all we need to do here is determine the width of our element so if it's from me we want to essentially align this box right here and it's going to be on the left hand side so we'll say align items end and if it's from not me so it's like this we're going to say align items start now if we save you can see that now this box never is any wider than the actual text inside of it which is exactly what we want so now we can try to send a message from here we'll just type in some gibberish click send go to incog and you can see that message has immediately shown up and we're able to communicate back and forth between these different users and it's all with a very very simple server now that we have our entire project built i want to show you how we can use in bold to do an automatic code review of our project if we just go to embold.io you can sign up for an account and you'll get brought to this page where you can create a new project we'll call this one what's app clone we won't need to give it a description we'll click create project and from here we need to link up our repository we're just going to be using git we can just copy the url for our repository paste it into here and then once we have that done we'll give it a name let's say what's app clone and you need to tell it what language you want to actually check in our case obviously we're going to be using javascript so once that's done we can just click link repository it's going to load up for a little bit and then we can just click this scan button now this scan may take a little while depending on how long your code base is as well as how many other scans are currently going on so once this is done i'll come back and show you the results now that our scan is complete you can see that we have a score of 4.29 and if we click on this we can get more information about our actual score so let's just come in here click on that and you can see that we have a quality gate that's been passed our overall rating our design rating code issues metrics duplication and hotspots this is a lot to take in so i'm going to show you the most important aspects in my opinion code issues and metrics are the most important parts of this tool so if we click on code issues we can see that we have 41 issues in the client folder here and it says that they're all low issues so we click on this a low issue is essentially kind of like a warning and you'll notice that most of these issues are from no unused vars so if we click on this you can see exactly the line this error occurs you can see that it says we're not using react react is undefined but never used and same thing with app here and this is from eslint and the reason this is happening is because it's eslint has a hard time working directly with react because jsx is not really a part of javascript so luckily with this tool we can modify the eslint rules or any of the rules for that matter and make them work exactly how we want them to for our particular project so one way that we could do that is on a line-by-line basis we could say we want to express this individual occurrence but in our case we kind of want to suppress all instances of this no unused vars so in order to do that let's navigate all the way back to our whatsapp column project and actually let's go one step further all the way back to here where we can click on these triple dots and inside here we can set up essentially different configurations whether it's for our quality gate or in our case for our code checker so we can just go to code checkers configuration and from here you can see we have eslint jshint gamma.js and all of these different rules we can even upload our own json configuration if you want to have a particular configuration in our case we want to hide that unused what was it unused import or something like that we'll just search for unused there we go no unused vars just uncheck that right there and essentially that's going to completely remove that exact instance of that hint for us so now if we go back and we just re-run our scan so we come in here and just say scan repository that's going to rescan our repository with that new you know js rule in place so that we no longer are checking for those instances of unused variables and as soon as this scan finishes i'll come back and show you the difference there we go that completed very quickly and you now see we're bumped up to a 4.95 out of 5 so we have essentially almost a perfect repository and if we go to our code issues we see we now only have one code issue if we click on this we'll see exactly what it says it just says here that if i click on this expected if condition curly javascript allows the admission of curly braces when a block contains only one statement however it's considered to be best practice to actually put those curly braces in so it's just saying we should have curly braces surrounding this instead of a one line if with no curly braces so we could disable this rule if we want or we could go back into our code and change this depending on your own personal preferences in my case i would probably get rid of this rule but it's entirely up to you now the next thing that we can look at are going to be metrics i think this is a great tool for figuring out exactly how good your code is so if we just go back here to our overall project let's go to the whatsapp clone again and we click over to our metrics this is going to give us all of our different metrics and you can see that we have one violation for accessing to foreign data and one for lack of cohesion methods and just by reading those names it's probably a little difficult to figure out exactly what that means so luckily you can actually click on any of these and it'll bring up the documentation saying exactly what this means exactly what you can do to fix it essentially and exactly how this problem comes about and it does it for all of these different types as you can see here lack of cohesion method the one that we also saw is in here it tells us the default threshold it gives us all the information that we actually need to fix these errors the nice thing about these metrics is these aren't really like hard and fast rules that you can apply to code like eslint is or prettier these are things more like hey your code maybe has this problem because it doesn't quite follow all these best practices and it helps you to structure your code in a way that makes you write better cleaner code instead of throwing everything inside of one giant function or one giant class another great feature about this tool is that you can really easily look at all of your tests for example test hungry methods your unit test all the things around testing you can check out in here so if we had test we could exactly look at all of our tests our different coverage and all of that good stuff we also look at a heat map which kind of describes where all of our different projects are so if we had some things that had a poor score for example all the way down here by negative five they would be a different color right now almost all of our components are essentially this nice green color and this one component over here has a slightly lower green color just because it doesn't quite meet all of the requirements because it has some of those eslint errors being thrown inside of it but as you can see green is really good because almost all of our components are showing up here as dark green and if we had components that maybe had a lot of errors they would show up as red on this heat map so it's easy to see what percentage of your code base is good code versus bad code just by looking at this heat map here and that's all it takes to create this whatsapp clone if you enjoyed this video make sure to check out my other videos linked over here and subscribe to the channel for more videos just like this thank you very much for watching and have a good day
Info
Channel: Web Dev Simplified
Views: 229,631
Rating: undefined out of 5
Keywords: webdevsimplified, whatsapp clone, whatsapp clone react, whatsapp clone reactjs, whatsapp clone react js, whatsapp clone react.js, socket.io, socket io react, socket io, socket.io react, socketio react, socket io js, socket io express, socket.io messaging app, messaging app js, messaging app javascript, messaging app socket js, messaging app node, messaging app node js, javascript messaging app, whatsapp javascript, whatsapp socket.io, whatsapp react js, javascript, js project
Id: tBr-PybP_9c
Channel Id: undefined
Length: 104min 7sec (6247 seconds)
Published: Sat Sep 05 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.