Build a Full Stack Multiplayer Tic Tac Toe with a Realtime Chat + Authentication - ReactJS

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey guys how's it going i'm back here with another video and today i decided to bring this video where i'm going to be showing you guys how to build a full stack application where the user is able to play a tic-tac-toe game um it's a multiplayer game so they will be able to play with another person while at the same time they will be able to chat with the other person and do a lot of other stuff as well so this application also includes authentication it has everything included it is using an api called the stream api which um facilitates a lot of the chat system and also all of the websocket connections that we're going to be using um throughout this application so um before we get into the video i want to kind of demo the application really quickly to you guys this is basically what we're going to be building so you can see i have um two different windows opened up inside of my computer it's kind of hard to fit both of the windows with the recording however i zoomed out a little bit that's why it looks kind of small but you can see there is a very simple sign up and login page now the styling i didn't worry that much about styling here um the api facilitates a lot of the styling they have a lot of good documentation teaching you how to style your your components um but if you're interested in checking out my styles which again it won't be that great because the main focus is working on the functionality of the application you can check the code in the description which will include everything we've done in this video so if you're interested in that you can just go there so you can see the application starts out by having um a login page and uh or a signup page i already have a couple accounts um already set up just for testing but um i'll just use one over here let's log in with the account i created with the username test and the password for this account is test as well so if you're able to log in you'll see that um it'll it'll bring you to this page which i'll zoom in a little bit just for a second so you can see so this page um includes um you're able to create or join a game or you're also able to log out so if i want to log out i can just click on this and then log in with the same account as before and everything will work perfectly all the information exists in cookies so it's very secure and very easy for us to access now if another user wants to login into another account for example this user can log in with the account test2 and the password test2 you can see that now both users are logged into different accounts the reason why i can do this is because this page over here this browser is in incognito and this one isn't so the cookies for them are different right so they were able to test how it would work for two different accounts so how exactly would the game work well the one whichever user wants to invite on the other user to play can write the username of the their rival or the the person they're playing against so this browser over here is logged in as the account test so i want to play against task 2 which is this account over here so i'm going to click on start and join game and you can see um you need to wait for the other player to join your game because or else you could just start playing without him right so the other player over here which is test2 will join in and put the username of the player on the left and start and join game and you can see that um now everything appears perfectly we're now able to play against each other this is the actual game we have here a tic-tac-toe board which is very common and we also have a little chest system over here on the left wants to start all they have to do is click on any of the cells for example i i click on this one and they will automatically be determined to be the x player now they can't click on any more cells because it's not their turn the turn now is for the player on the right when they can actually click on this one for example and the changes will be sending to each other to each player individually so you can see that it's all aligned they sync up perfectly and when a player wins you can see it's over right another cool thing is the fact that there's also a built-in chat system where you can basically set send chat messages to your player that you're playing against all this is powered by the api so um keep in mind that it will be very easy to develop something like this compared to developing the chat on your own using something like web just using plain web sockets right so for example if i want to say hey how's it going i'll put this over here and i'll click i'll just press enter and you can see the text message already appears on both accounts so it says that for me it says that i sent the message for this one it says that the test account sent the message you can do a lot of cool stuff the api has a lot of stuff for example built in one of them that i chose over here is reacting to messages so for example i send this message right this person over here can react to it by putting a heart for example and now i can react to the message i can also react by adding another reaction it's just small but really cool things that you can do with the api that you can play around on your own i didn't want to add a lot of the features but i'm going to be demonstrating them to you in this video now if you're done you can leave the game by click by clicking on this button and you can start a new game with another player if you want to or you can start with the same player and technically it will remember all the messages that you've sent in previous games so this is basically the application we're going to be building if you're not impressed with the ui um it's fine don't worry i like to do it this way so that i don't waste a lot of time in the video just doing css which isn't the main point of the video but if you're interested in watching the video stay tuned because we're going to be building this whole application in this tutorial so with that in mind let's get into the video so as you can see um we have over here opened up a vs code editor and i personally don't have anything in this project yet i just created a folder called tic-tac-toe tutorial and i opened the application inside of the folder so the first thing we want to do is we want to first of all divide our project into a client folder and a server folder the reason we're doing that is because the application is full stack so it is important to distinguish both the front end from the backend so i'll just say server and client now what i want to do is start out by focusing on the client which will be built with react so i'm going to open up a terminal over here and i'm going to change my directory to client like this and then i'm going to run yarn create react app like this now you can use npm it doesn't really matter at all i'm using yarn it won't change basically anything so feel free to use whatever you want while that is installing we can also start creating the server part of the application so i'm going to open another terminal over here so we have two at all times and the second one we're going to do differently we're going to change our directory to the server folder now that we're inside the server all i want to run is yarn init and this is basically going to generate a package.json file that will already build a lot of the initial stuff that we need so as you can see over here um and for the server we're going to create a source folder which is going to hold all of our server files so if we want to um create a server using express and ogs i need to create a file over here called index.js or you can call it whatever you want um and then in the package.json put the correct path towards um this file but for now let's leave all of this um behind and let's just go ahead and start working on the client since i think the react application was built yeah as you can see over here everything was built using the create react tab command so i'm gonna straight up just run yarn start inside of the client directory and it should start uh an application inside of this browser over here so it's going to be empty initially obviously it's going to start out with the files that come with create react app but as always i delete a couple files that come with the command so for example we're not going to be testing anything we're not going to be using the logo no css for the index so i'll just delete all of those files and as you can see over here now it should be fine i'll also come over here to this index.js over here and delete the index.css call and finally i'll just come to the app.js and delete the logo together with all of this stuff that comes with the create rec type command so you can see that now it should be working right it's just a blank page which is totally fine so before we start writing the code for our react application we need to install some of the packages that we're going to be using in this project so the first package i want to install and to install packages for either the client or the server i'm going to open up a new terminal which is not the one that's going to be used for for running both this the client and the the server this one is just for installing packages whenever i want and um i can toggle around going to the client folder uh like this um and then going back by using cd and double dots and i'll be back and if i want to go to the server i'll do the same thing right um but i right now i just want to go to the client folder and i want to run yarn add and the following packages are the ones we're going to be using first of all we're going to be using axios because we're going to be making api requests from our react application to our back end so we need to use some sort of library or just use the the fetch api that comes with javascript but i prefer to use access because i really like it so we're going to be using it in this video um and then what we need is um the universal uh cookie library so i'll say universal cookie and this library is super cool i used it in so many projects in the past basically it makes it so much simpler to have cookies in your application and manipulate them and delete them do whatever you want with them so i would recommend using it whenever you want and we're going to be using them to hold the authentication information for the users in our project then the next thing we need is both of the packages we're going to be using related to stream which is the api we're using in this video to create our application so the first one is going to be called stream chat and the second one is going to be called stream chat react so the stream chat is used for more of the logic part or communicating and connecting a user and the stream chat react is a library maint to give us some cool components that we can use in our application so now that we have all of them done i'll click enter and it should install all the packages we need so while that is happening let's start out writing the code for our application so right off the bat i want to create a folder inside of our source folder in react which will be called components and this folder will be used to handle and hold all of the components we're going to be using and we're going to be creating a lot of them so the first two we're going to be creating are the login component and the signup component so i'll just say sign up like this and both of these components will be used for authentication purposes as you may expect but i'm just going to run the the snippet rfc which i have installed and just generate this component over here and we'll do the same thing with the logging component um to generate it as you can see over here and what we want with both of these components uh is basically to just generate the the the form or the the inputs and buttons that we're going to have in order to allow user to connect to an account so for example in the signup component we're going to have over here a div uh wrapping everything around and i'm gonna even give it a class name um you don't need to do this if you're not gonna use my styles but i'm gonna be using some css that i wrote and i'm just gonna paste it so you guys can see it so um to make it work we need to put the class names that i'm gonna be that i used in the css so for this div i used sign up as a class name so we have to use it right now then we're going to add a label which uh will basically just say something simple like sign up form or sign up like this and below this we're just going to add all of the different inputs we're going to have in this form so for example i'm going to add an input over here with a placeholder which will say something like first name and then what we want to do is we want to add an on change to it because we need to detect when whenever there is a change in this input and that's basically it we're just going to have those two properties in each input now i'm going to copy this and paste it a couple times and now what are we going to put inside of this on change you might be asking well we need to keep track of what the user writes in this input and there's multiple ways of doing this one way is to create a state inside of our inside of our form and just updating that state to include whatever the user is writing in the input so what i'm going to do is i'm going to create a state over here which is going to be called user and the function will be set user and we're going to be using um the use state hook to do this like this so we're going to import use state over here at the top like this and um this stage will be an object now why will it be an object well it will start out as null because we the user didn't put any information to try to sign up initially but as you go we will be writing in each of the inputs and we'll be updating this object to contain a field for example called first name and the value will be equal to whatever the user typed on this input this doesn't make sense right now it will definitely make sense as we go as we add more inputs but the first input we can already start adding its property inside of the state and we can do this by coming over here to the unchanged and adding a function like this and this function will basically take in a an event over here from the onchange so we can have access to the target.value which is the actual value of the input while the user is typing on it and what i want to do is something like this i'm using github copilot in this tutorial by the way that's why i have some autocompletes but but i'll explain everything that i write throughout the video for example in this case over here what we did is we have this object called user it initializes as no so for example imagine if the object is like this and it has the property first name right and first name is equal to pedro and the user types jack on the first name input right on this input right here so what this on change is going to do is every time they type a new letter it's going to set the user object which includes the property first name to be to update its value to whatever the user is typing so what we're seeing here is we're saying we want to set the user object to be the same as was it what it was before so keep the whole object the same but change the property first name to be equal to the event.target.value which is what we're writing on the input and we want to do this for all of the inputs that we're going to have inside of this project so we're going to have another one for oh i need to close this over here like this we're going to have one for a last name because we need a last name for the user and we just change this to last name over here we're actually going to have a couple inputs so i'm just going to copy and paste the inputs that we're going to create and go over every one of them that we're going to have so as you can see we actually just added two more inputs one of them is for a username which each user needs a username and the other one is for password because each user needs a password so we have all of our inputs ready and we also have our state over here the the user state being updated to include whatever we're typing on our form so the last thing we need is to be able to sign up and click on a button to to send this information and authenticate it and register the user so that we actually have some sort of authentication system in our project so what we're going to do is we're going to add a button over here this button will say something like sign up like this and we'll have an unclick which for now um let's just ima create a function over here at the top called sign up we can say something like const sign up equals to just a simple function and inside of here for now let's let's just not do absolutely anything but we need to grab this signup function name and pass it as an on click to our sign up button so now that we have all of this done over here for signup let's do something very similar for login and the reason why i want to do for login first right now and the reason why i want to do it for login before even doing anything with the signup function is because um i want to do both the login and the signup forms ui before going to the back end and doing the the logic behind the authentication of our project so i'm just gonna copy basically all everything that i wrote for the sign up and paste it inside of the login because it will be very similar they will be basically the same so i'm just going to paste it over here and the main difference actually is that we're not going to need to ask for the first name or the last name because to log in all you need is a username and a password right and also we're gonna change this to login instead of signup and this to login instead of signup now at the bottom over here you can see it still says sign up so we'll change this to login and the function still says sign up and so we'll change it to login and we'll have to create a login function over here as well so we'll keep it like this and now we have both the login and the signup components done so we can check it out uh nothing appears in our page for obvious reasons because we haven't called either the login or the signup component yet so to do that we'll come over here into our app component and over here we just want to call the sign up first like this and then the login component over here so login and we need to import both the login and the signup i don't know why the the login imported automatically but the signup didn't but we'll just autocomplete over here and you need to import both of them from our components folder now we should start seeing the form appearing in our page it says set user is not defined oh i know what this is basically in our login component we we have the the set user because this is how we were doing it for our sign up but it's a bit different and the reason why it is a bit different is because in the sign up we have a lot of pieces of information that we need to keep track of for the user before logging in we really just need to keep track of a username and a password so we don't need to create a state that holds an object for it we can do a little bit different if we wanted we could do the the same thing we did with the sign up by creating a user state but actually for this one i'm just going to create a username state like this and i'll also create a password state like this and each one will represent the value of the input individually so i'll grab the set username and change it over here both of them will be strings so that means that i can just say set a username equal to event.target.value and set password to be event.target.value as well so i'll say event dot target dot value so i wrote it wrong so here so now that we have both of them kind of working we're not um calling anything wrong and now that we have both of them working we just need to import the usage hook from the login as well because we only did it on the sign up component so now you can see the form at least appears in our screen obviously as i mentioned the ui doesn't look remotely as similar as what i had in the beginning of the video because as we go i'm going to be adding some css to make it look better and for now we don't need to worry about css so we have now done both the login and the signup components which means that we can start working with the backend of our application so i'm going to close both of these things over here and open up the server folder together with the index.js file this file over here is kind of the entry point of our server our server will start inside of this um file right it will start right over here and before we write any code i want to point out that by default when you have node.js in your application to import modules you have to use the old way of importing modules in javascript so for example if i want to import express i have to say const express equals to require express but i don't want to do it this way i want to do it how javascript does it nowadays which is how react does it you can see it's by saying import so if you don't know how to change and allow you to use the import notation for for express and node.js all you have to do is you just have to come over here and add the type on your package.json and add the module type and now you're able to import just like you do in react it's just a small thing but i'm going to be using this kind of notation since it is more commonly used nowadays in javascript so what we want to start by doing is um creating and importing the express variable from the express library so we currently haven't installed anything inside of our back end so we need to install the express library by coming into our terminal going into the server file because you can see we were in the client so i went back and i'll say server and now what i want to do is i want to use yarn add and i want to add the following packages the first one is the express package so i'll say express the second one is nodemon which for those who don't know it's just a package that allows us to whenever we save a change in our server um it will basically restart the server so that we can see the changes happening in our back-end and then what i want to have is the uuid library this library is going to be useful so that we can generate unique ids for each user which you technically don't need but it's very useful because that's how we identify each user right each user and application will have a different id so this library is widely used for situations like this and then what we need is course because we need to define course in order to establish a connection between our front end and our back end and finally i want to install bcrypt so that we can hash our passwords um whenever a user tries to create an account we don't want to um keep track of passwords that are not hashed because it's dangerous so we want to use bigcrypt to do something like that so i'm going to press enter and it will start installing all of the libraries that we just listed so i'm going to close this right now and let's try writing the code for our backend so i'm going to say import express from the express library because we need express to create our server then i want to say import course from the course library so that we can again make our connection work between our react app to our backend then i'm going to say const app equals to express so we can create an express app and then i'll just say app dot use and i'm going to use first of all course again so to make course work and i'm going to use the express.json function so that we can apply this middleware to all of our routes in order to make us be able to accept json as a form of data when we send data from the front end all of this are basic stuff for express and i i will not go over all the basic stuff for express because um the store is a little bit more advanced than that so if you aren't that familiar with express and um or just react in general um i wouldn't recommend this tutorial because it's a little bit advanced um but i have other tutorials explaining all of this if you're interested just check it out so now that i have set up both cores and the express.json middlewares i'll just come over here to the bottom and say app.listen and i'll put a port the port i'm going to be using is 3001 since react is running on 3000 and i'm just going to put a little function over here which will basically for now just console log of like a message saying something like um i don't know um server is running on poor 3001. something like this right so i'm going to save this and this is the basic structure of our api now we're going to be creating routes inside of our api because we're going to have our authentication route now when you're creating a backend using express if we're going to have multiple routes in your application you're recommended to create a routes folder and just separate your routes into different routes right to different files and just organize everything perfectly but the thing is with this application we are going to only need two routes one for login and one for signing up so we don't really need to create routes for it like i use the the express routing system so we're just gonna write all of our backend logic inside of this file which should be fine because it isn't a lot so the thing is um we're now in a point where we have to set up our stream account because we're gonna be using um some information from it in order to connect to it so we have to start by going to a browser and going into getstream.io to create an account now the i have a link for it in the description if you want to check it out just click on the link and you'll be brought to this website over here and you click on try stream you can see a lot of stuff will appear a lot of websites use stream as you can see and then you can come down here at the bottom and type your email you can see mine is already over here just type an email you want to create your account with it is completely free and then you can put a purse an organization name which in my opinion you can just put like your name so i would pay like pedro um and then whatever you want then you can put your password just create a password i already have an account so i'm not gonna do any of this but um you put all this information and where you're gonna be brought to is the following so you will be brought to this account or this page over here this is your dashboard page or just like where you can see all of your information for your api you're also able to see your um key so your api key and your secret and you can do a lot of stuff because um stream actually has two different types of um branches in their api um the one we're going to be using is the chat one which allows us to create systems like our game and an actual chat systems so you just go to this page over here and what we want to do is we want to keep track of both the key and the secret now those two pieces of information are exactly what are going to make us be able to connect to stream and also if you if you're using the documentation um all the the keys and the the secrets there are all personalized to you so if you go to the documentation everything will be personalized to your account so um with that in mind we just need to keep track of this information from out for now but we want to come over here to our index.js and start out by creating two different variables one is going to be called the api key like this and i'm going to set it equal to whatever api key we have over here which my case is this one but it is completely different for you you have to check out which one is yours and then we need to create one called the api secret which we will set it equal to this secret over here we're going to click on it to review and then just copy it this is extremely important you shouldn't show this to anyone the reason why i'm showing it to you is because i'm going to create a new account immediately when i post this video so it doesn't really matter at the end of the day so um you create both of these variables and one thing i would recommend is to use environment variables i don't personally need it but if you want you can just create an en.env file and make this both of this stuff into environment variables so you don't post your api keys and your secrets into your github account at least don't do it publicly because that will be dangerous and um i don't know it's just not something you should do so what we want to do now that we have both of these pieces of information is we want to start out by importing the the stream chat library into this file so we do that by coming over here at the top and i'm going to import like this from the stream chat library so stream chat like this and i'm going to import the stream like stream chat class which is this one over here then i'm going to come down here at the bottom and i'm going to create a variable called server client which will be basically the instance of our connection right and we can just fill it out by setting it equal to new stream chat and then passing the api key and the api secret like this now one thing we have to do is we need to say dot get instance so that we as i mentioned create this and make this into an instance of the stream chat api so this over here can be used for many things mainly to be able to connect a user and create an account in inside of our stream dashboard so we're going to use this a lot inside of our server then what we want to do is we need to create the two routes that are going to exist in our project so the first one is the um signup route so i'm going to say app.post slash signup like this and the second one is going to be the the login route so i'll just copy this perfectly like this um and just post it and paste it again and just change this to login now as you might know in express what you do to create a route is you just pass a rack and res and and inside of here uh we just write the code for what this route is going to do so for the sign up is going to be mainly a lot of stuff actually the it's going to be mainly just grabbing the information that the user typed in the front end then generating the hash password the user id and then creating the account in stream so let's go in that order let's start out by getting the information the user is going to pass from the front end to the back end and the information will be all of that inputs that we created in our um signup components so if you go to sign up in our front end you might remember that we had an input called first name one called last name one call username and one called password right so we need to we will receive all of those four properties over here as an object um into our backends so we'll just receive them inside of the rect.body so we just have to say something like first name like this last name and username and finally the password like this so when we grab all of those pieces of information from the body what we want to do is we want to create a user id so say user id is equal to uuid v4 now what exactly is uuidv4 as i mentioned uuid is one of the biggest um random id generators of libraries out there and we need to import it inside of our project so that we can use it as as i just showed you so the way we're gonna import it is we're gonna come here at the top and say import from the uuid library and i want to import the v4 uh ver so it means version four there have different versions where you can use but this one um seems like it seems like it fit for what we want and i'm going to say as uid34 because this is standard for when you're using this library so this should generate a random id with like a lot of characters a lot of numbers and letters and everything which is completely random in the sense that um no two users will have the same id which is exactly what we want it's almost impossible because of the length of the id that this generates so we're just going to set the user id to be equal to this now what we want to do is we want to hash the password that the user typed from the front end right so the way we hash it is by creating a variable called hash password and we're going to be using the the library called big crypt that we created or we we downloaded when we were downloading the libraries um and to import bigcrypt we just say import bigcrypt like this and we'll save from the big crypt library i've used big crypt so many times in the past and it's really good um it's actually really simple to use when you've used once or twice you'll you'll see it's pretty simple so what we have to do now is the thing is when you're using big crypt it will return a promise so we need to make this function asynchronous so that we can say await over here and say bcrypt the hash password and we put password as the first argument to the hash function um and the second one is just um i believe it's called salt uh yes all rounds um this is basically i always leave it as 10. um i wouldn't change it if i were you this should be fine so now that we have hashed our password we want to be able to create a token from the stream api so what is the token the token will just be um some sort of as the name implies a token that will identify the user and we need to send that to the front-end so that the front-end knows which user is authenticated so to do that we're going to say const token and set it equal to server client so we're going to be using the server client which is the instance of our connection to the stream api and we're going to say dots create token like this and we're going to pass the user id which is exactly what we need to do to create a token that's why we created the user id and now they have the token the user id the hash passwords and and everything like that all we have to do is just send it back to um to our front end so i'm going to say rest.json and i'm going to send all of those pieces of information the token the first name the last name the username uh like this and also the hashed password because we don't want to keep track of the the normal password so oh also we might need the user id so i'm just going to send the user id as well so this is basically it for the sign up it's pretty simple pretty short the main part over here is creating the user id and creating the token because that will be very useful in the front end also if we want to handle errors we need to put a try and catch around this whole thing just in case any errors occur we'll just say something like this we'll say try this whole thing if there's any errors then i want to catch this error and i want to say res.json and i want to resend back the error message that we receive and just close this like this and then save it so this is how we're going to be handling our errors we'll receive all of our errors back as responses from our api requests now um what i want to do is i actually want to handle this making the request for the signup before doing the login because the login will be much more complicated than the the sign up so when we make this request we're going to get back all of this pieces of information right so what i want to do is i'm going to go to our signup component so this is the react component which we created for the sign up and i want to straight up just start writing the sign up function that will be called when you click the sign up button so the signup function will be very simple all is going to have is an api request to our backend and send all the data that we that the user typed for the user um state over here so to do that we need to use the axis library which we installed in the beginning um to make that api call so i'll say import axios from axios like this and then i'll just come over here and i'll do something like this i'll say exuse dot post like this and the post it is a post request because in the back end we defined it as a post request and if you recall we put slash sign up right so the url that we're going to put over here will be http um then a colon then double slashes local host 3001 slash signup because this is the the url for our api this is the port in which our api is running and this is the route for the signup request then what we want to do is we want to come over here and pass the body that we're going to receive in the back-end as i mentioned the body will be an object which will be built upon using a first name a last name a username and a password which is exactly what our user state over here is right just keep tracks of what we write on the input so all we have to do is pass the user as the body over here and when this request is done we can say uh dot then over here and just grab the response and create uh or write what we're gonna do when we get a response back from our backend because we want to make the request wait for the back-end to to create the user into and connect it to to the stream api and then send everything back over here so technically what we want uh is to get back this um information over here so the hash password the user id the token everything that was created so i'll just do it by copying this and creating destructuring it from the the response dot data so rest.data and i'll just paste everything inside of here like this and these are the pieces of information we really need to have in our front end now what do we do with those pieces of information well to keep the user authenticated we need to use the cookie library that i installed and set a cookie for each one of this variables so to make that work we're going to come over here at the top and we're going to import the the cookie library so we're going to say import cookies from um universal cookie and then we're going to copy this over here go over here the like right before we define a state and we're going to say const cookies equal to new cookies like this so this is how you instantiate um or how do you you utilize this library and then we can use this cookies variable throughout our application to either get or set cookies inside of our browser in our case over here we want to set some cookies where we want to set a cookie which will be called for example token and the token cookie will be equal to the the token variable that we just got from the response of our api so we want to do something exactly like this for all of the variables that we created and it will be all these variables over here so i'll just paste um the same command for all of them and be back in a second see we set the cookies for all of them which is perfect so now that we have all of them stored in our cookies we are able to sign up um and at least get the information back inside of our front tent now what exactly are we going to do with this cookies right where are we setting our cookies to be equal to this variables well the reason for that is because um when you're connecting a user front-end to the stream api we have to have access to this so what we're going to do to make this work is we're going to come over here to our app.js component so the higher level component in our application and then we're gonna basically just start implementing all of the stream chat um stuff in react so i'm gonna import over here from the stream chat library and what i want to import is the stream chat class similar to what we did in our backend but now we know front-end and this over here will allow us to come over here at the bottom right before the the return statement and we can create a client reference similar to what we did in the back end as well we'll just set it equal to um stream chat like this dot get instance and then we'll just pass the api key for our application so just like we did with the backend we need to copy the api key that we that we have so i'm going to create the same variable over here but in our front end so just create it over here and just pass it inside of the get instance now a thing i just realized is that um when we go to our back end i actually did something wrong we shouldn't put the new um keyword over here it should just be streamchat.getinstance similar to what we're doing right now in the front end so just change that and it should be fine so i'm going to close that and now i want to use this client to connect the person inside of this react app or the person who opens the website with their account so how are we going to do that well we're going to first of all try to get the token cookie so if it's if someone try to log in or sign up they should have a cookie called token and if they don't then it means they're not signed up or they haven't logged in and if they do it means they've logged in so to do that we need to have access to the cookies so i'll do something exactly how we did over here with the sign up i'll import the cookie library but in the app.js and i'll generate the the cookie class right over here so that we have access to it and what i want to do is i want to create a variable called token which will be equal to the cookies.get token so we're going to try to get the token if it has been set it means that someone logged in if it hasn't it means that someone hasn't logged in and to keep track of that we're going to say if the token has been set then we're going to have to connect the user by using the client variable and saying client.connect user so this function over here will take in a couple pieces of information and will further connect the current user to their stream account so this function over here will basically connect a user to their specific account now the difference with the how we did over here in our back end is that um when we get an instance for example when you say stream chat dot get instance and we pass our api key and our api is secret um we're connecting our project with the stream platform so we're we're basically making a connection between our code and the platform but when we connect a user with the the platform keep track of users that you create in your application and you're just connecting to the account already in the stream um platform right so each user will have different pieces of information that information will be the the kind of the form that we created in the sign up and login so we're going to pass over here that a couple pieces of information for example we're going to pass the id which will be the cookies.get user id so i'll just say user id like this then we're gonna pass the name and the name um although the name it says name it's actually the username so we have to pass cookies dot get username the reason for this is because uh stream uses uh name as the default name for this field so we just have to pass name and then we just have to add this three um pieces of information over here the first name the last name and the hash password so all of this uh basically creates a user and we're just saying that we want to connect to the user that has those um pieces of information right and then we're gonna put a comma over here and pass the current token which is the code the token that we got from the cookies so that we can further connect this user now now that we have this done um it should actually connect to the correct account if they have a token and we can actually this returns a promise so we can say dot then and even check to see if this actually worked so what i'll do is i'll grab a user from this dot then because you can and i'll just console log which user is um logged in right so this technically should um work meaning that if we try to sign up to an account in our project it should create an account inside of our application and um we should be able to see this user being console logged the issue is that oh let's test it out i'm going to come over here to our vs code and i'm going to try to run our backend which currently isn't running and the way to run it is i actually need to make node one work if you recall we installed known one because it will allow us to make changes to our backend and when we save it it will restart the server so to do that i'll just come over here add a script tag like this and instead of the script tag i'll add a start script like this um i have to put a like i need this is json so i have to do like this start and then i'll just run the command node mon and then we put the path to our index file which is source slash index dot js i'm going to save this and we should we can just run yarn start and it should be starting our server as you can see over here and it says servers running on port 3001 meaning that if everything is right when we try to create a user it should make the api request sign up the user into stream then set all the cookies and in our app.js when it when the cookies are set it should automatically satisfy this condition meaning it will connect the user to the user which has those those those ids and that password and then just console log the information about the user so let's test it out i'm going to inspect element and i'm going to refresh the page and in our console currently there's nothing but if i try to sign up by putting for example the let's create a user called um nate right let's just call him nate the last name will be backer i don't know i'm just making up names the username will be simple let's actually just make the username nate and the password nate i'm going to click sign up you should see that um our if we go to application um you can see that all of those pieces of information are set into our cookies right application shows the cookies that you have in your browser so that worked right so how do we check to see if the user is logged in well let's refresh our page and you can see that now the token was set so it actually connected to the user and when it finished connecting it console logged the user that we can now see over here you can see that each user um includes a bunch of information about you so it means we correctly connected our front end to the stream api now that was kind of simple in the sense that um what we're going to do now is a little bit harder because now we you want to be able to log into an account um if we already have created an account for that user so to make that work we're going to come into our index.js and we're going to go into our login route over here so i'm just going to put the rack in res like we did for the input so i'll say rec and res and i'll grab both the username and the password that are going to be sent um through the body of this request so i'll say username and password like this and then the first thing that we want to do inside of this um the the login route is we want to try to see if this user already exists because if we're trying to log in with an account that doesn't exist it shouldn't work right so the way we do this is we're going to say const users and we're going to be using the stream api library to try to query a user with a specific username so we don't have to create a database or anything the stream api handles everything for us as you can see over here so we can use the api to maybe fetch some data which in this case we want to fetch the a certain user given a certain username just to see if it exists so we can say server client dot query users like this and we pass over here a name property and the username of the user we want to try to query why are we passing this because if someone puts a username that is right and types it out we're going to get it over here through the body and we're going to check this we're going to try to find the user with that username and it will return back a user's array containing all the users that match this username um if the array is empty so if um there is the users.length i'll just do users.length is equal to zero um then it means that the user doesn't exist in the database so we can just return the arrest.json and the json will be something saying like um will be a message saying something like user not found so we can just say something like this just to say that we you try to log in with an account that doesn't exist but if it exists then we want to basically create a variable called um password matches um or something like yeah password match because what we're going to do is we're going to try to compare the password of the user that exists in the database with the password that the user tried to to log in with so to do that we we have to use bitcrypt because the password in the database is hashed right because we hashed it over here but the password that the user is typing is not hashed so what big crypt does is it basically hashes the password that the person um typed it out and compares both of them to see if it is the same so i'm going to say password match is equal to bigcrypt.compair which is a function in bankrupt and we passed both passwords we passed the one that the user tried to log in with and the password currently in the database so we can say users um and the first user dot um hashed password right so we can just save this and one thing is um bitcrypt as i mentioned is it needs to be asynchronous also this over here has to be asynchronous so we make this function async and we put a weight before this and a wait before the big crypt command as well so what do we do with password match well basically this will be kind of acting like a boolean so if they match means it's working means that the user can log in they put the correct credentials so we'll say if password match then then we want to log in right but before that we also need to keep get the token of the user because the token is is really it's crucial that the person in the client um has the token of the user that exists inside of a stream but when you sign up you have access to that token because we sent we create the token and send it back over here but when we log in we don't have access to the token because we haven't created it so how exactly would we handle that well we can just grab the token directly from the oh we can just create a new token directly inside of the login so i'll just say over here const token equals to serverclient.createtoken just like we did inside of our um signup signup routes so i'll just create the token as well and instead of the password match conditional we want to return back all the information that we just acquired so i'm going to say res.json and we want to send back the token like this so i'm going to send token also the first name of the user which by the way when you're trying to log in you don't have the inputs for first name and last name so um the way we pass it is by saying first name and grabbing the first name existing inside of the user that we just found in the stream database right so we can have access to all of their information by using this user's array over here so we'll just say users zero meaning the first user in the array which technically should be one user because you shouldn't be able to create multiple accounts with the same username and then we'll say first name over here and we'll do the same for all of the other variables and i'll be back in a second when i pasted all of them as you can see we did the same thing for the last name and the same thing for the user id but usually we already have had access to it because it was right over here and the password we technically don't need it um for the login so we're just sending back all of this information over here and similar to the sign up we're going to try and catch to er to do some error handling so i'm going to say try and then if none of this works um then we which we know there's an error so i'm going to catch that error um and just rest.json back a message or an error message i'm containing the error i'll say like this so i'm going to save this and this technically should be it for the backend we won't be doing any more things in the backend because now the login and the signup should be correct um so let's go to the login file over here so we'll just open up the login component and over here i'll even just close up the the sign up what we want to do is we want to make the access request to the login route so i just pasted it over here because it is very similar to what we did with the sign up so i didn't want to rewrite everything again all you have to do is make a axis post request um but now to the login routes instead of the signup route and instead of just passing the user in this case we have individual values so we have username and password so we just created an object and pass the username and password as the body to this request then um when this request is done we grab back the token user id last name first name username everything and we set the cookies to be equal to that so as you can see i just pasted everything inside of here the reason why i did that is because you can see it's very similar to what we did with the sign up so i didn't want to spend time just rewriting everything um you can see we made a post request using x use but instead of using the signup route we made a request to the login route and we passed the username and the password as the body to this request then we just grabbed all the information and set the cookies to be equal to the information that we got i also imported exodus at the top so don't forget to do this as well so if this is working when we log in it should set the cookies to be the correct information and when we refresh the page it should automatically connect to the correct user so let's try it out so i'll just oh it says cookies is not defined because we actually need to do the same thing we did on all of our components so far by importing the cookies library and then just saying const cookies is equal to new cookies like this and now it should be working so what we want to do is we want to try to technically log out because currently we're logged in we'll be continuously logged in because no matter what we do if we close a browser if we open a new tab or whatever everything will be stored in the cookies and they will they'll be kept here for as long as we want so um technically to log out all you have to do is delete all of the cookies by manually deleting them like this obviously there's uh we're going to do a way where we have a button where when you click on it you can log out automatically but for now let's just keep it like this so technically i just logged out because i deleted all the cookies you can see it doesn't console log the user info anymore now let's test it out let's click on login and put the username for the user we created the username is nate and the password is nate as well so i'll say nate over here when i click login it should create all of the cookies which is something that happens but then again it says undefined meaning that something is wrong with this user so let's try to to see what is wrong i realize what i actually did wrong i should have came over here and set the users 0 dot id to be the user id not the user id variable that we created over here because we don't have access to it so this is technically the error i apologize for it so we can just save it like this and if we delete all of this again as you can see and try logging in again you can see that now the information is correct it's actually storing the correct information for the user trying to log in meaning that if we refresh the page it will make the request and actually log in the user so this is amazing um we're able to log in with our account and we're able to sign up with our accounts meaning that the first part of this tutorial is done all of the authentication stuff is kind of done now we start working with the more interesting part of the tutorial so one thing i want to do now is i want to create a state that is going to keep track of whether or not the user is authenticated or not so that we don't need to keep refreshing the page every time we log in or sign up so to do that i'm gonna come over here and say const um yeah and then create a state called is off and then set is auth like this and set it equal to use state and it will automatically import from react as you can see over here and this will be a boolean which initially will be false but the important thing is that when we connect our user instead of console logging the user we want to set is auth to be equal to true like this meaning that um whenever someone logs in to their account um for example someone who is already logged in and they close their browser and just go into the url or someone who refreshes their page this will automatically set the is auth state to be equal to true now when you click login and when you click sign up technically this doesn't happen automatically you will still have to refresh your page um but we can fix this by passing this set is off um state as um like a prop to both of these components like this and like this i'll just paste it over here and then on our on both of the components we can grab this information as props by saying set is off and when we finish the login which is something that happens over here after we set the cookies we can just say set is auth is equal to true because now we are logged in and we'll do the same thing for the signup component i'll just come over here and i'll grab the prop and say set is off and over here same thing as the login i'll just put set is off is equal to true so now that we have this done um we can use this is auth state to kind of conditionally render our app to show whatever we want depending if the user is authenticated or not and the first thing we want to show is we want to do something like this we're going to say if the user is authenticated then we want to render the game which for now will be just a text saying game but obviously we'll create some components to fulfill this but if it's not authenticated then i want to show the sign up and login components so i'll just um wrap both of this around with this and also put a fragment over here because every like every group of components need to have a parent so we just put this fragment and this should be working you can see that since we are logged in it will say game but if we were not it wouldn't say would show the the form as we had before now really quickly just so we can log out whenever we want to we can also create a little um log out kind of log out like button and the way we do this is i'll just come over here and i'll instead of saying game i'll actually just say the button just put the button right over here and the button will say log out and it will have an on click to a function called log out so i'll say log out and we'll create this function right over here at the top this function will be very straightforward because i mentioned this in the past um the way we're logging out is we're just technically removing our um our cookies right so we can just say something like this we can just say cookies.remove each of the cookies that we currently have inside of our browser and if we remove all of them technically we should log out the user now now we still might be connected to our to the stream platform um the user that is logged in and clicked on this button um so to fulfill that the disconnect we're gonna say client the disconnect user and this should fully disconnect and remove all the tokens and log out the user that clicks on the button so let's try that out if i come over here and i click on logout um it should have logged out oh it did i actually did if we refresh the page it actually shows this right um the problem is that we need to set is auth over here to be equal to false because now the user will technically be logged out so let's try that again let's log in with nate and then the password is nate and let's log in you see this appears um okay ignored this um and now we are logged in when i click log out the form appears again okay so what we want to do now is we want to start actually implementing um all of the connections so that our game is able to work between two players that are in different computers so how exactly are we going to do that well the first thing i want to do is i want to create a component called the game component and this component will handle all of that kind of connection stuff and also a big portion of the chat system that we're gonna have in our inner project so i'm gonna just say game.js and create the component then i'm gonna say rfc like we said for the other components just so we can generate the component automatically now we want to import this component inside of our app.js um so i'll just put it right over here i'm actually just say like a game it needs to be capitalized so i'll say game and it should import the component over here at the top and then we're just going to self close it like this now it's giving us an error because obviously as i mentioned like this we can have two sibling components without a parent one um but we're not gonna do we're not gonna put a fragment on this one because we actually need to wrap our whole game around with a built-in component that exists from the stream chat react library so we're going to come over here and import from the stream chat react library the chat component so we'll say chat now what exactly will this this help us with well it will it will basically allow us to um pass our client over here as um props to this um component and it will create a context where we will be able to access this client in any component inside of here so that we don't have to keep passing the client variable as props to all the components consistently just so we have access to it we can just create this chat over here and put it around the the components we want to have access to the client and pass the client as a prop to this and then whenever we want to access for example user information user id we can just use um a hook that comes with the library inside of this components over here to grab the client directly so this is something that is really cool and we're going to be using inside of our project then we're going to come over here to our game component um actually i'll call this um join game because we're actually going to maybe create another um game component and i feel like the name for that one is better to be game so i'll just call this join game instead and this will be the component which will be used to um basically just uh handle all that that inputs where we're able to to to write the name of our of our opponent or arrival and actually join a connection between us and them so i just call this join game and i'll come over here we want to have is we want to have a div with a class name called probably like joint gain like this and inside of here what we want to put is we want to put um maybe like an h4 tag saying create game or join game um just so that we we have some sort of visual representation that this is where we're going to to create a game then we need to put an input which will ask for the the username of the person you want to play tic-tac-toe um with so i'll put a placeholder over here and say something like username of rival and then i'll just add the unchanged to this input and the unchange is really important because we need to create a state which will keep hold of the name of the u of the username of the rival you want to play against so what exactly will we want to call this well we can just say it um we can just come over here and create a state by saying cost and we'll call it rival username and set rival username and set equal to use state like this and it will automatically import and this will be a string so we can just keep it like this now we'll save it like this and on the unchanged we're going to do it similar to what we did with the login component we'll say event and then set the event or set the the rival username to be equal to event dot target dot value so event.target.value like this and when we save this um now we should be keeping track of the the username of the rival but we also need to put a button below the input so that when you click on it um we want to be able to establish that connection right and actually start the game so we'll say um join slash start game and there's important aspect of this library and just websockets in general which i think you guys should know so basically in order to establish a connection between two users we're going to create what is known as like a room or in using the stream api we call it a channel it's kind of like a a closed space a close connection between a certain amount of users or members where all of the events and every uh message and everything that happens only exists inside of the connection so only the members inside the connection are able to see the the data so in this case we want to create a channel using the api with only two users which will be the user which requests um to play like both users that play the game against each other so those are the two only members of the channel so they're the only ones who are going to be able to see the chat messages and the play moves for the tic-tac-toe so when we click on this button technically we want to create a channel right between these two users so i'm going to create a function called create channel which will be very very important so i'm going to say cost create channel and let's start creating this function now the way we will do this is we'll start out by um saying const and trying to um query the user with the username that we wrote in the in this input over here so why exactly are we doing this because when you create a channel between multiple users you need to pass um the id of the users that will be present in that channel which will technically be the idea of of myself so like the user trying to create this channel and the idea of the the user they want to play tic-tac-toe with so right now we don't want to make the people memorize other people's user ids because it's a huge mix of letters and numbers we just want to be easy and simple just put the username of your friend or the person you want to fight with and um it should all handle it should get the id um instead of the logic right so that's what we want to do we want to grab the username of the user and try to get its id based on that so we'll just say something like response like this cost response and we're going to use the the client from the api to um query users with this username now you might be thinking we don't have access to this client variable over here it exists in the app.js file and that's true right it exists over here but as i mentioned when we pass the chat component over here when we when we make it be the parent component of all these components over here now we can use something from the the react uh no the stream chat react library called the use chat um context so i'll say use chat context and it is a hook that will just allow us to have access to the client so i can say const equal to use chat context and i can grab the client directly from here so that we don't have to pass it as props through all of these components so now we can query the users like this by saying client.query users but we need to pass the username of the of the client or of the user we want to query so i'll pass an object and pass name which as i mentioned in the past is how they call username in the api and then i'll say i'll pass this little simple notation over here which means equal to so we're basically saying i want to query a user with the username equal to um the rival username state which we created so rival username and if this works it will try to grab the user information for the user you want to play against with store it in this response variable which by the way we need to make this function um asynchronous so that this works because then we'll say await over here now when we get this response back what we want to say is we're going to say if over here like if um response dot users dot length is equal to zero so if we if no user is found with a username then we can even just alert like a message saying yo you try to i play a game a game against someone who doesn't exist so we can say user not found right just to get a visual um confirmation of if the user actually exists and then i'll return so that we don't continue um checking anything else because everything that will come after this in this function assumes that the user exists so if the user exists then we want to say const new channel and we want to create a channel between both users so we're going to say await and then grab the client and say client.channel like this and we need to pass a type um there's multiple types of channels um that you can use in stream you if i were you i would check them out um but in a like a website or a program like we're building over here the messaging type makes more sense all of them will just customize the different features you can use but for the messaging type it will work perfectly for us so that's the one we're going to be using then you need to specify which members will have access to this channel and members are just the the users of this um of this channel right so i'll just say members like this and will be the two users that are gonna partake in this game which is myself and whoever i type as my rival so we need to pass the id for them my id i can just access by saying client.user id like this or just grabbing through the cookies which we also have access to but i'll just do it like this because it's simpler and the sec the id for the second user is actually the id that we grabbed from the response right we did all of this so that we could grab the id based on the username so we can say response dot users then grab the first user and say dot id now the reason why it is like this is if you actually console log the response you can see that this is the format of how they give back a response i've done that already and i know that this is how you grab the id based on the response so i'll just save this right now and we can come over here and assume that a new channel was created between those two users so now connection was established so um then we'll say await new channel dot watch now why are we saying this well um when you wanna like enter and and listen to events and and messages and data from a room or a channel you need to say channel.watch this is something you need to do or else you won't be listening to them you won't be inside of that connection so after we create the channel we're just saying okay i want to participate in this channel then um what we want to do is i actually want to create a state that is going to hold this channel so the state will be called um channel so i'll just say const channel like this and set channel and then we'll just set this equal to initially it should be null so i'll set this equal to um use state and i'll just set a null initially but when we finish the channel we'll just set the channel to be equal to the new channel that we created so this is awesome but what happens when we actually um create a channel well when we create a channel we wanna is when we click on the button right it's going to say create or join game we click on that button it should create the channel and we want to start the game so what we have to do is create a state over here which is going to hold on to the information of whether or not you've clicked on this button or not so if you've actually started your connection or not um one way we can do this is by creating a new state but actually a smart way of doing it without creating new state is just checking to see if the channel is null so i can do something like this i can come over here so we want to wrap all of this around with this with jsx because we're going to put some some logic and i want to make this into a fragment because we have to do this or else it won't work and the logic will be as follows um if the channel is not exist so it's not null then we want to for now just render an h1 tag say game started but we'll obviously change it in a bit but for now let's just do that but if the channel is no then we want to render all of this piece of information because it starts as null right until you click on the join game button this channel state will be no so we can check this out right um obviously the join game um thing is not being rendered right now actually it is it's it's right over here so what we're going to do is log in with some sort of account so i'll say nate and nate and you can see that now um you see it says um here create game username of your rival join start game you can either log out you can do whatever you want um so what we're going to do is i want to put the username of our rival technically there's no one uh that we've created yet um so what i'm gonna do is so technically what i'm gonna do is i'm gonna open up an incognito tab over here and i'm gonna go to my local host as i mentioned the reason why i'm using a tab that is incognito and a tab that isn't is because the tab that is incognito doesn't keep track of the same cookies as your normal browser so um we can have two different accounts logged in at the same time and we're gonna create another user called um i don't know matt and the last name will be uh matt will i don't know i don't know about names i hate coming up with names during the video but i'll just say matt as the username and matt as the password i'm going to sign up and now we're logged in as matt as you can see on our application over here you see all of the cookies are correct so now we have two users with different usernames and we can actually connect them into a game how do we check that well i'm gonna put over here the name for matt because they are my rival and i'm gonna click join start game and you can see it says game started for this one i'm going to say nate because it is the other user and i'm going to click join game and it will say game started now there's an issue right the issue is that this one started before this one if you recall in the demo i had a little message saying like oh waiting for the other user to join before he could before the game actually started because you don't want to be seeing the tic-tac-toe thing and interacting with it before the other user actually appears in the game so we want to detect that before we show this message over here so how do we do that well i'm going to come over here and i'm going to actually delete this create this game start thing and create the game component that i mentioned in the in the beginning that we're going to be um creating so i'm going to say game.js and create the component so this component will be very important um it will be the component that basically we render when we when the game starts so i'm going to say game over here and it should have automatically imported as you can see over here also we're going to wrap it around with another component that comes from the stream chat react and this component is called the channel component similar to the to the chat component that we used over here basically we can wrap all of this around with the channel component and we'll have access to the channel um inside of any components inside of here if we pass um our the channel that we created as props to this channel component like this i'll say channel and we created a state called channel that we can just pass over here so i'll say channel perfect so now we're wrapping this around with this and we have our game component that will be called when we start the game so i'll come over here so inside of this component over here we want to have two return statements we have the first return statement which will be um the return statement that is like fundament that is basically the the one that normally will return and the other one will um be a return statement that will only um exist if um either one of the the users trying to connect to the game hasn't connected yet so that's the check we want to play we want to check to see if there's two players currently connected in the game and if there's not then we want to return a message saying something like um i don't know waiting for other player to join something like this right and how exactly are we going to do that well the stream chat api allows you to detect if players join or just detect to see how many players currently exist in this connection and the way we do it is we actually have to have access to the channel directly as props to this game component over here now i know i i said that we can use it as context but for this specific case we need access to it directly so i'm going to pass it as channel just for this component like this and for the next ones we're going to use um the the properties the hooks that come with the api so for this one we'll just leave it like this and then we'll come over here and we're going to grab this channel as props and what we want to do is we're going to create a state called the maybe let's call it like players joined and it will be a boolean which if it's true it means that the two players are currently in the game if it's false it means that only one player is in the game so we'll say players joined and set players joined and we're going to set this equal to be use state like this and the initial state of it will be very simple with the channel we can actually see if how many players are in the game or in this connection by saying channel dot state dot watcher account and study asking if it's equal to two because if it is then there is two players in the current connection if it's not it means it's false so what we want to do is in this if statement we'll say if not players join so if there's not two players in the game then show this message if there is then um continue with the game right so you can see that if i refresh my page um with both of the both of the the pages that i have so i'll open the incognito as well and i refresh it and i try to join a game with um with matt right so this one is matte and this one is nate so i'll put matt over here you can see it will say waiting for other place to join and if i click on this one over here and i put nate you should see that it's still this one works right it says gain meaning that it detected that there's two players but this one over here still thinks there's only one player the reason for that is because when this one tried to log in it automatically knew that another player was there but this one when it logged in there was only one player and when this one logged in it didn't detect to see if there was any changes to the watcher account so what we can do is we can use events in the stream api which is something that we're going to be using throughout this tutorial to detect any changes that occurred to the watcher account so an event exists inside of the channel and we can listen to this event by saying something like channel dot on so channel.on we can pass a name to an event and it will keep checking to see if there was any changes to or if we received any messages from this this specific event type so um it's built into on the the api that there is an event called user dot watching um dot start and this event basically um just will be called whenever some another user starts um watching this channel or joins this channel so what we can do is we can grab this event over here and just create um a function out of it if this event occurs and if it occurs we want to set the player's joint to be equal to event dot watcher count is equal to two so that's basically what we're doing we're just setting it equal every time there's a change to the watch account this also will be called um so technically now if we save this and we try all of that again i'll just um close this and i'll come to the browser and i'll open the other browser again and we just refresh the page um and try to join the game again so i'll put over here matt join game it says waiting for other player to join and i try to log in with try to play against nate on this one technically now both should say game and that's exactly what happens because this one detect that this player joined meaning that we connected both players into the same channel perfectly and it works nicely so now that we have that done um we we're now kinda getting close to start doing the the actual game the tic-tac-toe and the actual chat that will exist in our application so the way we're going to do it is as follows we're going to inside of this return statement over here instead of returning game we're going to return a div with a class name of game container like this and we're going to return two different or three different things the first one is a component that we're going to create called board and this will hold all of the logic for the tic-tac-toe the second thing will be um and i'll just i'll just put for now a comment over here it will be the stuff related to the chat so like the chat between the two players and finally it will be a button where the two players can basically leave the game so i'll say leave game button i'm just organizing it right now because we're going to start by doing the tic-tac-toe game so instead of this board component we're going to create the tic-tac-toe logic and everything related to it so what i want to do is i want to create a component called board and i'm going to say board.js and i'm going to say rfce and create the component the board component will start out pretty simple it will start out with a div with the class name of board and another div with the class name of row so we'll just create both of them like this um and obviously there will be um three rows and each row will have one square so i'll just give a class name of row like this and inside of each row we want to add um a square right but a square will actually be a component that we're going to create over here so i'm going to create another component called square and i accidentally called it dot j instead of dot g s so i'll just fix that so square.js and we'll just say rfce and for now let's just keep it like this but in our board and i'll just close all of this over here so we can have more space in our board we're just going to manually put over here three squares for each row so i'll just say square and copy and paste it three times and then just copy the row and paste it two more times so that we have three nine squares in total which is technically what a tic-tac-toe um game look like right so with this in mind um what we have to do is we have to recognize how is this going to work well we need to keep track of um the state of each of each square right we're going to have um like a an x and an uh a zero or an x or o determining um which player is which player and we're going to have a board which will be represented by a state so we'll say const board and set board and this state will be equal to an array of nine elements each element in this array will represent which square we it represents right so it will have nine because there's nine squares in a tic-tac-toe board and initially all of them will be empty so i'm just going to make them an empty string like this right so i'll paste them 2 3 4 5 6 7 8 9. so i have nine of them right now there is a thing when we click on one of the squares for example we click on the fourth square which is this one over here we should um if we are the x player we should fill this up with an x and this is how we're going to kind of keep track of the state of the application so initially we'll be all empty but when we click on a square it should change um so what are we going to do with this square component over here well the square component will be very simple it will first of all just have a div with a class name of square and for the i haven't added any css yet um before the the the tic tac toe port the board part i do need to add the css because it is fundamental to making it look like an actual tic-tac-toe so i'm going to say square over here and we're going to pass in an on click to this div you can do that in react you can just pass an on click and this on click will actually be a function that we grab as props so we're going to say uh two square that's will be that will be the name of the of the function and when you click on the square it should call this function um now just do like this so i'll just paste it like this and it should be fine and the value inside of it shouldn't be square actually what should be written inside of this div is either an empty string an x like this or an o right it this is the the square and how it looks inside of the board so how we're going to represent this well we're going to keep track of these values um over here and pass it as props so we're just going to render it like this we'll just say that the value will be whatever value is passed as props so we can save this right here and this is the square component so we go to the board and for each square we need to pass both a val and a two square so for the choose square which is the the state we need um i'm gonna just save it like this and did i actually import oh i didn't import the square component so i'll just say import square from dot slash square so we're gonna pass the true square function and this function for now will be empty but we're gonna create it in a bit and we also need to pass a vowel for it now the vowel is kind of self-explanatory the value will be passed based on whatever value currently exists in the board array so for the first square we can just say that the value is equal to board index at 0 because this is what we're going to be changing right and the value should change depending on this so i'll copy this and put a value to each of the squares we won't do the choose squares function yet but for now let's just do for the value and i'll be back in a second okay so as you can see i added the value for our all of the squares and i put the the value of the board um the index of the board that corresponds to each square now let's add the css so that it actually looks like um something right because you can see first of all it says board not defined did we did we import the board in game let me see uh we didn't right so i'll just say import board from um dot slash board so we'll save this you can see that um there's a bunch of errors first of all uh the error of the the two square i'll just delete it for now but i want to show you guys how the the board looks because it doesn't look like anything now um if i come over here and i join a game with someone else so i'll i'll join a game with matt and this should be oh they're already in the nade is already in the game so when you join the game um you can see it's all empty but if i start filling out the the board like i put an x over here um like this i put an x and i put an o and i don't know i put an x on this one um i just fill it out you can see that if i save this it should show the values over here but they're not styled in a way that it looks like a tic-tac-toe game right so the styling will be as follows i'll come to the app.css and i'll delete all of this and i'll just paste the styling that i wrote for tic-tac-toe game if you want you can check it out you can look at it i actually did a tic-tac-toe tutorial but not a multiplayer one not even close to the extent of this project so if you want to check out of the minor details of how to build the tic-tac-toe you can check out this video um but for now i'll just copy and paste the the styling that i wrote and i'll go over what each thing does okay guys so i just pasted all the css and i the css for this file even includes some css for other stuff like the login and signup page and the join game button but as you can see it looks like a tic-tac-toe right it just doesn't work because we haven't wrote any of the logic for it but what exactly did i put inside of the css file well for the app component i just um like put a width a height and just made the color blue then this is all the styling for the inputs you can check them out but it's pretty simple i'm just making the inputs look like um actual inputs because if you see over here if i log out um this is how it looks now because of the styling so if i log in again as nate um i need to put the the correct styling uh the correct um it needs to be lowercase so i'll just press enter over here and log in you can see this also changed um and now we have like a button um and uh an input but it looks a little bit better but it still doesn't look amazing i'll just click matte over here and join the game and you can see that this is all the styling that i added um now for the board what i did is i set a width and a height for the board so the width is 500 the height is 500 i made a little border around it and i made the flex direction to be column because then for the row what i did is there's three rows so each row is 33 of the board right so the height and then for the square each square is also 33 of the width right so there's three squares so each square will occupy 33 because that's 100 divided by 33 or approximate right so then i just added some colors to them um added some styling for the the elements inside of it and this is how it looks so if you want to check out the css just go over it in your own time um but now we're going to go ahead and start making this look functional so to make this look functional we need to to do the following so we first need to take into account that um there is a player right so you need to know if you're either an x or an uh an o right you can either be one of them now it depends on who starts the game we don't want to make it so that um it's predetermined right it's just whoever starts the game is x and whoever is the second one to play is the o so what we're going to do is we're going to create a verb over here call it player and set player as the function for the state and then we're going to set it equal to use state and this date will be a string so we'll put it will start as an x because that's technically what a player the first player should be and we're also going to create another state called turn now what exactly is the turn well when we're playing multiplayer tic-tac-toe we need to know which turn is which right and we're going to use the stream api um events to keep track of that because we're actually going to be listening for events for when the other player plays and we're going to change the turn and which player you're you are based on that so i'll create a state called turn and the function will be set turn and the turn initially will be x as well so that's how we're going to represent the player is who you are the the turn is who should be playing right now then what we want to do is we want to start playing to write the true square function so i'll come over here and i'll just say const choose square like this and i'm going to set it equal to a normal function but this function should take in a square now why should it take in a square because it depends on which square you're trying to choose so in the two square props that we have over here all we have to do is we'll pass the true square like this and this function will actually just be calling the choose square function with the square that we want to choose so the first one will be zero but um the other ones will be um one two three four five so i'm just gonna copy and and paste it so we'll have to do one by one and i'm back in a second okay so as you can see i just filled it up i put the true square for each of them and now it should be okay so now what are we going to do with this choose square function right we have access to the square but what exactly are what exactly do we want to do well the first thing we want to do is we want to check to see if the the the square is currently empty or not why do we want to do that because i don't want to choose a square that is already filled right if there's an x over here i don't want to choose it right not to mention i also don't want to choose a square when it's not my turn so i want to first first off just say if turn is equal to the player so if the turn is equal to me and the the board and the current square that i'm trying to click is equal to the empty string mean that there no one has filled this square yet then i want to continue going forward i don't want to do anything if this condition isn't satisfied then what i want to do is i want to change the turn right immediately i want to change the turn because um now it's the other person's turn right so i'm going to say set turn is equal to the opposite of what it is right now how do i do that well i say okay if the player is equal to x because we know the turn right now is equal to the player because this condition was satisfied so say if the player is equal to x then i want to make the the turn be equal to to the o else make it equal to the x like this so we're just alternating the the term then i want to do i want to basically set the board to be equal to its new value with the the square field so how exactly are we going to do that well the board is just an array so we can basically just say board dot map and map through the array and grab its like the current value of each index and the index like this and then for each element all we want to check to see is if the index of this specific element in the array is equal to the square um and the value is imp is empty meaning that um we're trying to to fill a an element that is empty um then we want to return the player and what do we mean by return the player well we're going to change the value of this current element in the array to be equal to whatever we return which will be the player meaning that if we're at the player x and we press when we click on for example square the second square this one over here so it will call the function two square with the value one so square will be equal to one meaning that it will come over here and map to the board until it finds the the square with the index equals to one which will be this one over here so we'll find on the second iteration of the loop and then it will set it equal to um x instead of just an empty uh string like this because i am player x so this is technically what we can do but if it doesn't um if it isn't the square that we're trying to choose then just just keep it how it is we'll just say return vol because it is the current value just keep it exactly how it was before we don't want to change it we only want to change the square that we're trying to choose so this technically should work if we try it out if i click on one of the squares um it doesn't and let me check why oh it works now i just i don't know why i just refreshed the page and now it works so you can see i keep clicking on it and i can't anymore because it's not my turn anymore but if i go again and refresh it and i try to join a game with nate you can see that if i click on oh it's i am late so i should join a game with matt if i click on one of the squares it will fill it with the player right which is x but it doesn't allow me to click more because it's not my turn now it's the other person's turn now you can see the other person didn't receive the x because we didn't send this information so how are we going to send um like the information of us choosing a square or like a game move um through to the channel right so that the other person can listen to it well there's a very interesting function that you can call using the channel called send event and events in the stream api are basically like this um you can just send data to a certain channel and um in any format you want and the people in that channel will be able to listen and receive that data um bi-directionally so they can listen to it consistently um as they want right so i'll just say a weight over here because i need to to make this asynchronous for this work and i'll just say um channel dot um oh i just realized we don't have the channel on this um specific um component but what we can do is since we um in our game over here no it wasn't even a game it was on on the join game since on the drawing game we wrapped all of this around with this channel thing we don't need to pass it as props anymore what we can do is we can come to the board over here and import from um from the stream react app library so stream chat react and we can import this hook called the use channel state context so this is just a context that includes the channel so that we have to pass it as props so just say const equals to use channel state context and grab the channel directly from here like this perfectly so now we can use the channel and say something like channel dot send event so the send event allows us to send an event to everyone in this channel and the event it goes as follows you can put a an object and it has to have a type and it has to have some sort of other um fulfillment right i call it data because it will be the data that we're trying to send in this event so the type let's call it gain move because it is the type that we want to it's a game move right we're we're choosing a square and then the data that we want to send is whatever we want the other player to to know when we make a game move so the first thing we want them to know is which square we just filled right so i want to say square um equals to square so i want to create a a property called square and its value will be equal to the square that they're trying to choose now in javascript if you have a an object with a key which is the same as the value you don't need to do it like this you can just do it like this and it should be fine um and the second piece of information that we want is which player played this um this move right so i'll just say player and it will send which player made this move so that we know which one um when we're listening to it right so now when we make this move it should be listening it should be sending this event to everyone in this channel but how do we listen to this event if we are the other player well the way we do it is similar to how we listened to whether or not someone joined the game or not we're going to come down here at the bottom we're going to say channel.on like this and on the channel.on we're gonna grab the event and with this what we can do is we can basically say okay if the event dot type the reason why i'm doing this is because um this will listen to any event that exists on this channel but we only want to listen to the event that is of type equal to game move game move like this and i only want to listen to this if the person who sent this event isn't me because no matter if i sent this event or not i'm still in the channel so i'll receive this as well so i just want to say okay i only want to listen to this if the type is game move and also if the event dot user.id which is you can grab the idea of the user who sent this event by accessing it like this is not equal to the current id that i have so i can grab it by many ways i can grab it by using the client which we can do it by just again using the use um chat context this one over here that we've used so far so we can just do it like this const um equal to use chat um context and we can just grab the client directly from here and then actually i think i typed clients so client and then over here at the bottom right over here i can just say client dot user id and now if both of those conditions are satisfied we can start writing our play so we can set the board to be equal to the new board with the game move implemented by the person who sent this event so if this player over here makes a move now we want to change our own board based on that so i'm just going to say set board and it's actually pretty similar to this one over here so i'll just copy and paste it um like this and the difference is that now we want to check to see if the index is equal to the event dot oh it got messed up so i'll just say event dot data dot square like this and if the value is empty then i don't want to return the player i actually want to return the event dot data dot player because we want to fill it in with not ourselves but with whichever player made this move so now that we have that done um we can see that this should be working right let me open up both um things over here if i make a move on this one the other one should listen to it too now the problem is um i still don't have access to this one but i still have access to this one over here but it thinks i am an x as well right so technically we're we're both the same player the reason for that is because um when we listen to this event over here initially player is set to x right but um i decide to ask for both players no matter what so what we want to do is whichever player listens to to the event so the sec the second person to make a move should automatically become the opposite of x so well like a little hack that we can use to fix this is coming over here and setting the player to be equal to um the opposite of what the player that sent this move is so let's actually create a um thing called player over here um let's call it current player and set it equal to um event.data.player so if the player that just sent this event is an x then we want to make the current player be an o but if it's not then we want to keep it though we're going to keep it as an x like this and we'll set the player to be equal to this but not only that but we also set the turn to be equal to this so that it's now your turn right because initially turn starts as an x as well so now both the yourself and the turn will be um oh and this only will apply to the to the second player to play because um we're we're listening to this game move right um this will not occur if you sent the event so now actually i believe it should be working let's check it out our flash will refresh both both of the pages um we'll try to play with mats and this one will try to play with nate um i'll join the game now it appears and the first player makes a move thus he probably can't make a move anymore because now it's the other person's turn now the second player makes a move and you can see it recognizes that the second player is an o instead of an x and they can also make a move they need to wait for the the other player to make a move and yeah it goes on um we can play forever like this uh until someone wins right which right now we're not detecting if someone wins so you can see this person just won um but we didn't detect it so that's exactly what we're going to do right now so to check if someone wins or not it's a little bit more complicated and the reason for that is because um there are only a certain amount of patterns that can exist for a winning move to occur so there's actually this list of patterns which is pre-made i didn't make this this is just how tic-tac-toe works i'm going to be using it in our project so that we're able to detect if someone wins or not so i'm going to create this file called patterns or winning patterns i'll just say winning patterns like this winning patterns dot yes and all this gonna have is the following it will have an array with all of the possible um winning patterns and this is the array right um so you can win if you are a player with an x on the zero which is this one over here with an x on the one which is this one over here and with an x on the two which is this one over here and you can either also win if you have all the other combinations right so this are all the combinations possible for a player to win in tic-tac-toe so what we want to do with that is we'll come over here to our board and we'll create a function called check if win or check win so we'll just come over here and we'll just say um const check when yeah let's just go like this and this function um when called we'll check to see if the board currently has a winning player right so basically to do that we'll have to have access to the patterns array which we created um in that winning pattern file so we'll say import from dot slash actually i need to go back twice because it's not in the components it's a file called winning patterns and we'll grab the patterns um array like this and we'll just come down here at the bottom for the check win part and we'll say patterns dot for each because we're going to loop through each of the patterns and for each parent pattern we'll grab the pattern like this and just run a check to see if this pattern exists in the in the current state of the board so how we do that is we'll say first of all okay the first player is equal to um the the element in the in like whichever player just filled the first um item in this pattern so we'll say board curve pattern zero and i know this might be a little bit confusing but believe me when it's working i'll go over it again just so you guys can get a better understanding on it but what we're doing over here is we're just saying okay um we're checking every pattern right so if the the first the the really the first like square of that pattern is already filled by by a player that is not you then why continue moving forward so let's say if first player is not is equal to zero which is meaning that it's empty then don't even continue looking for this pattern because it hasn't fulfilled yet so return then we want to create a state a variable called found winning pattern so why are we doing this like this because we're going to initialize this variable as true meaning that we we assume we're going to find a winning pattern right now but then we're going to check for the current pattern to see if it fails or not so if it wins or not and if it doesn't fail it means it is a winning pattern if it fails it means it is not so the check is the following we'll loop through each of the patterns over here like we'll loop through all these elements over here like zero one and two and check to see if for zero one and two uh either it's filled with axes or filled with zeros we assume it is gonna win so we assume it is either filled with x's or zeros but if inside of this loop we ended end up finding uh one of the elements with index to not be equal to the current player right then we want to set the found winning pattern to be equal to false um and then breaking the circle now we assume it's true first because it is easier to do it this way we just find um one of the like we check to see uh if it fails at any point and if it fails then we just set it equal to false and then we know that it it didn't um find the winning pattern but after this over here we'll just say if we actually found one then we basically want to we won right we we know we want because we found a winning pattern we found either a row full of x's or a row full of o's create a state called result which let's just create it on the the game file over here and this state over here the reason why i'm creating it over here is because i want to have access to it outside of the board so i'll just say um use state and we'll create one a state called result and we'll set it equal to set result and then on this use state we're just going to pass an object it will be an object with with two properties the first one is which player was the winner and if the game is currently um playing or someone won so the winner is just standing with the player who won and the state is just if the the game is running or not so initially no one won so we're going to say none and initially the state is also not because no one we're still playing so what we do now is we go to our board and pass both the result and the the set result as props like this so we'll say set result and result and then what we do is we'll save this we'll come to our board over here and if we found a winning pattern we'll just say set result um is equal to and we need to it auto completes because we haven't grabbed a set result in result from the props over here so we'll say result and set result and then all we have to do now is we'll come down here at the bottom and if we want we'll just say set result equal to the winner being the the board and curb pattern so the reason why we're doing this way is because we know that the winning play exists at this current pattern so if we just grab whichever either x or all filled this this um this the board at this specific index then we know which player won right because that they found a winning pattern and the state will be um probably like one meaning that someone won the game so um we can also alert this match this message for now so we can just alert like a winner and then put the the name of the winner which will be this over here and we can check to see if this is working but how are we going to check right we created this function called check win but we didn't call it anywhere so where exactly will we do that well the way we do this is every time there is a change in the board so every time someone makes a move we really want to check if right now the board has someone winning so we'll make a use effect over here which will do exactly that the user effect is a an amazing hook and react which basically it will be called every time there's a change in a state that we specify in this dependency area over here so we'll just specify that whenever there's a change in the board state we want to check if someone won so we'll call the check win um function and we can check this out right now let's test it out um we'll start out with this person um then i'll i'll play this then i'll try this one i'll try this one and then i'll win with this one and what should happen is an alert message should appear and as you can see it says winner and on this one it says winner 2. so it means we are detecting if someone won which is amazing now there's other stuff we have to do for example we have to check if someone tied so to check if someone tied is pretty similar to the check win function we'll just come right below it and because like if someone tied we shouldn't continue moving forward right so i'll say const check if type and we'll just put over here like this and we'll just do the following we'll assume that the whole board is filled because that's the only way that um that someone tied the game if it is if there's no um cells or squares in the board that are empty so we'll just assume it is filled like this and it's equal to true um then we'll come down here and go through each element in the board by saying board dot four each like we did before and grabbing each square and just checking to see if if the square is equal to empty meaning that there is an empty cell or an empty square then we just set field to be equal to false so we we do the same logic that we did over here we assume it's true but then if we find a breaking case we we just set it to false um and then we'll come down here and if at the end of checking all the squares none of them was empty it means that field will never be set to false so it means that it is completely filled and then meaning that um the game is tied because no one won and it's completely um there's no more squares to choose so the set result to be equal to um maybe i don't know to say winner equal to none again just set it to none and then i'll set the the state to be equal to a tie right so um i'll change this to one like in lowercase ladder so so we know but um there's currently three states there's none which means no one one then there's one which is someone one and then there's tie which means someone typed so now what we do is we just call this check if tai in the over here as well and i want to also alert a message so you guys also have a confirmation so i'll just alert a message over here saying game tied like this and then what i'll do is i'll just come over here refresh the page it says curve pattern not defined what does it mean by that it says on line 63 oh i accidentally forgot to remove this this is not related to the tie function is related to the the winning function so now let's just join the game again i'll open up on both things um just refresh the page now let's play against matt and let's play against nate and you can see that if i try to tie the game so let's just make it so that um like i don't know we'll just make it as so that no one wins um how do i make this i'll put this here it's kind of hard to make you lose on purpose yeah now it's tied right so it realizes the game is tired because all the squares are filled and no one won which means we're checking this correctly so this is almost all of the logic that we have to write for um the tic-tac-toe right because what else do we have to do for this um now it's just like playing around with um displaying the results if you want to and just play around with the styling if you want to as well but now we're going to transition into the part of the tutorial where we incorporate the chat system into this project okay so now that we have the logic for the game done let's start building the logic for the chat so the chat is going to be much simpler than you might expect uh the reason for that is because the stream api literally um is meant for this you know so they have a lot of built-in components that are going to make this way easier than it should be um compared to like tutorials i have on how to build chat like um from scratch um it just takes a lot of time because you need to deal with a lot of stuff so with the stream api what you can do is use their built-in chat components that come from the stream react um no stream chat react library so we're gonna come here at the top and we're gonna import some stuff from the stream chat react library so the first thing i want to import is a window and a window is just a component used in stream where we wrap it around the where we want to have our chat right then we want to also import the message list component and also the message input component so what exactly are both of this components well basically the message list over here will display the list of all the messages in the between two users and the message input will basically display uh the inputs that you can use to send a message right so for the message um list we're gonna do it directly over here where i wrote chat i'm gonna delete this and i'm gonna add the window like this so i'm going to wrap everything around the window and then i'm going to add the message list so the message list takes in a lot of props if you want to you can check them out there's a lot of things you can do with it this are all the props you can actually see um but i'm just going to use a couple of them so the first thing i want to do is um i want to hide delete messages so basically this over here is a prop um by default um if you delete a message from the chat it will and i'll save this so just so you guys can already start seeing the chats um let me just refresh this page let's see if it will appear if i put met i joined the game um it's not appearing but uh it's because we still have to add other stuff but basically um by default if you um try to delete a message it will like keep a message there saying oh this person deleted this message so um we're just gonna leave it like this um so if you delete a message you don't have to but but for now we're not gonna add any props because we still need to add the message input component over here like this um and we can save this let's see if it appears and yeah as you can see over here um right below our thing it appears to have a little message system which we can type a message and technically if we press enter you can see it says delivered right so i know the ui is all broken up but if i open up my other page you can see the messages are indeed already being transferred right there are two different accounts and you can just send messages between the accounts and both of them will receive so it was that easy you don't have to do any other thing you just put three components one on top of each other and stream will handle absolutely everything now there's a lot of customizations that you need to that you can use right and this is exactly what we're going to be doing from now on the first thing i want to customize is the fact that um like at least for our project there's a lot of the features that you don't really need for example i don't need to be able to reply to anyone so um i don't want to have that um also i don't want to be able to pin comments which is something you can do just like on youtube you can also edit messages which to be honest it's a it's a game so i don't you won't be needing to edit messages i like to have the re like the reaction one which is this one over here you can see you can react to a message um but what i want to do is um i want to take all those options out so it doesn't get clustered like it is right now and breaks all of our ui also i don't want to be able to send files um through the game because honestly it doesn't really make sense you're playing tic-tac-toe why would you be saying sending files or images or anything so to remove the option of sending files i'll just add the no files prop to the message input then um there's a thing as well there's this little thing at the top over here which i don't like basically just says the date so i'm gonna remove that by adding the disable date operator the date separator and you can see that that thing disappears all of this stuff you can check out by looking at the documentation they have a thousand different props i just played around with them and this is the best this is the best outcome that i could find um you can also um so there's this reactions right um you can also make it so that when you react to something this whole thing this closes so it just kind of makes sense and you can do that by adding the close reaction selection selector on click and now if i react to something it should close right as you can see but it's kind of kind of sketchy because the ui is kind of breaking so what do we want to do now um i have a lot of css that i that i added to this to this project that will basically fix all of this ui issues now the css um it's kind of it's kind of difficult because um you have to play around with each of the styles that are already predetermined by stream however um i'll paste the css right now and i'm back in a second and i'll go over each one of them okay so as you can see i just pasted the css and i actually created a new file called chat.css just so i can like distinguish the css for everything other than the chat and the one for the chat because the chat one is big um and i also imported the chat.css file in the game.js file and on the chat.css what i did was i did the following i basically gave some styling for the game container so that it made some sense and as you can see this this is how it's styled right now um we still have to make a few fixes don't worry but it's already looking a lot better um then i i added some styles to the lists and you might be asking what are these class names over here because i didn't use any of them well in the documentation for stream they list out what each of the elements over here like what the class name is for each of the elements over here so just got to take a look at them and style them however you want and this is all the styling i had to do to customize it however i want it now there is a couple stuff as well that um that i still need to do for example i said that i want to i don't want to have all of this options over here they are great like i want to be able to delete a message for example that would be awesome but um there's an issue like why would i have to do it if it's a game like a tic-tac-toe it doesn't like it doesn't really require all of that and the good thing about stream is that you can just make it so that you don't have all of these options right you can customize whichever features you're interested in so in our case the features we're really interested in really are maybe the delete but for short just the reaction one so the way we do this is we come to our message list and we can actually pass a property called message actions and it is an array containing all the actions that you want or all the features that you want inside of your messages so that might imply the the reply the pin feature the edit feature the delete feature there's a list of all of them um but the only one we want to keep is the react at least for now so we'll just say i want to keep the react feature now i would recommend taking a look at how you specify each of the features but as you can see if i put the react feature over here and it's the only feature i want now if i refresh the page and we go into the thing again um it should be the only option right just the reaction feature and there's not like the other ones aren't there anymore i don't know why this broke but yeah um the feature uh the features were removed which is great so um there's another thing it says that this message was deleted because we deleted a message a way to remove this message of like saying that you deleted a message is by adding the hide deleted messages prop and you can see now that message was deleted now you might be thinking okay what about all this stuff over here it looks kind of weird um you do like you might be asking i did why did you delete the no why did you add the no files prop if you can still choose files um we're gonna fix this because with the inputs used to write um the messages you can actually customize it pretty well um the way we do this is the following we need to create a component just for this specific input so i'll create a component over here called custom input like this custom it.js and we'll make it a component and what i want to do is i i want to come over here and just follow exactly what the documentation says for creating a custom input now i already read the documentation and they have a few examples this was the best example i found which is basically it already comes with all of the class names already added and everything for the css but basically this is a structure over input you won't have a lot of the options it won't have the the emoji picker which by the way you can pick an emoji which is really cool it already comes with all of this it won't have that um none of this um signs or anything which are really cool um but it will have it will be pretty simple we'll have the the search um like the the writing the type your message inputs and we'll also have the button to submit it so all we need for that is a button and we also need the chat autocomplete um component this chat autocomplete is basically um this input over here and it's a component that we get from um the stream chat react library so i'll say from chat react and i'll just put chat autocomplete and this handles absolutely everything from submitting the the message and sending the data to to the server and everything it will do absolutely everything for you um and all you have to do is you can see there's this handle submit function over here i didn't create this function and i don't need to because um all we have to do is just um import this directly from stream chat react by using the use message input context and just grabbing the the the handle submit function directly from this so i'll say use message input context and grab the handle submit now the way the reason why i customized this input is just because i wanted to remove a lot of the stuff and you can see it looks pretty simple now but how do we make it so that this input is what is being displayed in our project well the way to do it is we need to go to where we are defining our channel right where we have the channel component and that component exists in the join game component over here so you see this is where we're calling we're wrapping everything around with the channel and this component takes in as prop an input and basically whatever a custom react component we pass over here will be replacing the input component that we have inside of this which is this one over here so we can just pass the custom input like this and import it over here at the top so i'll just say import custom input from dot slash custom input and now if i save this you can see that um i need to refresh this and then try to go again uh you can see it looks perfect now i can type my messages um and send those messages to the people um i can even send messages like this by pressing the button as well and you can see that um the other person is receiving it as well um it's kind of i need to refresh the page for this to work but i'm going to zoom out a little bit as well but i'm going to try to get into as nate and you can see i received all the messages and i can send it from this one as well and it will receive perfectly on the other account as well so technically this is almost it right because we have the chat done and it was way simpler than all the other stuff we've done so far so what do we want to do now well if you're done with the game you kind of want to leave the game right so how do we implement some sort of functionality to leave the game well it's pretty simple we'll come to the game component over here and right over here we're just going to add a leave game button so we'll add a button over here and it will say leave gain and on the on click for this function we're going to basically just just tell the channel to stop watching like tell our channel to stop um updating so we'll stop paying attention to what the other person is doing so we start receiving messages we'll stop um like stop uh reading moves whatever it happens we're gonna we're just going to unsubscribe from this connection and we'll do this by saying by making this function async and saying await channel dot stop watching which is a function from channel and then we just want to set the the channel to be equal to um no again right so if you recall we have this channel state over here uh it's on the joined game we have this channel state over here and initially it's no but when you join a game it becomes the channel right so now in the game component we want to have access to the set channel function so i'll say set channel and over here i can just say that after when we stop when we leave the game i just want to set the channel to be equal to no again and i'll grab side channel from here at the top as well now you can see that if i click on leave game it automatically leaves the game and i'm not in the game anymore i can even refresh and you can see i'm not in the game um and yeah that's that's literally it now we're able to um to leave the game whenever we want to now the last thing we want to do is um just display the winner right so entering the game against the mat and i'll try to win the game so let me grab matt over here and i don't know i'll try to do something like this then i'll try to do something like this and then this uh is it matt no it just took a while but yeah i'll win the game and it says winner and that's fine but um what i want to do is that when it when someone's winning i want to display on the screen that that person won and we created the result state over here for something like this so i'll just put it right over here um on the leave game thing i'll just put it right below it i don't really care i'll just say h1 and if someone won so i'll wrap this around with a conditional so i'll say if result dot state not equal to none because if no one won or no untied it will be none then i want to display whatever state it is so what are we what do we want to state well i want to say actually i'll make this into a a div um and i'll say something like this if um if this result dot state um actually i'll just make this equal i'll just put two conditionals yeah i'll say something like if result.state is equal to uh one then we just wanna display a little message saying something like um the player who won so result dot winner won the game like this one the game and then what i want to do is i want to say if the state is a tie so tie then i just want to say gang tied and let's also remove the alert messages because that's kind of annoying let's go to the board and i'll remove this alert messages over here so let's check it out let's save everything come over here i'll open the other game as well and let's refresh this um and let's zoom out on this one as well so we can see it better it's hard to fit everything into this into one screen so okay let's play nate against matt and matt against nate so now the game starts um we'll try to make um nate win so nate just won and you can see x won the game so it says x won the game now let's try um again but let's try um tying the game just to test it out um nate and let's try tying but time is kind of annoying um let's see uh it's hard not to tie for some reason okay now yeah ah i think i won no it tied oh that's a that's a that's a bug you can see um it checked for the tie before it checked for the win which is interesting now what happened is it checked for that it checked for the tie after so it updated the state after so if we just put this right over here first then it's gonna assume it tied first and then it's gonna check if it went and if it wins it's gonna correctly say that this person won the game as you can see over here so now it's working perfectly um but yeah that's basically it so that's basically it for the video um the code and the video is pretty long i'm sure of that um although i did i tried my best not to add any css or not focus at all in css i know that this video is going to be massive but i always wanted to make a video like this where i just do a huge project that is full stack where i focus a lot on the logic not on the looks of it you can play around with the looks we all know that um css and you can copy css css isn't um that complicated um especially because if you're working as a developer most of the times you won't be doing css even if you're a front-end developer people would build components for you and you would just use pre-built components so actually understanding the logic and working with the api is the most important part and that was the focus of the video that's what i wanted to to to teach you guys and yeah that's basically it this video wouldn't be possible without um without stream um their platform is like amazing and they also help support the video because it's kind of hard to to make a video that is super long like this a lot of you guys always request um videos that are like extremely long with complete like full stack applications with a lot of features and it's usually hard because it requires a lot of preparation a lot of work just to put out a video like this so thank you stream because they were able to provide this to me um not only just sponsoring the video but also because the platform is really nice it just facilitated a lot of the stuff that i had to do so i wanted to thank them for sponsoring this video and yeah that's basically if you want to check out the link it will be in my bio and yeah i really hope you guys enjoyed this video if you enjoyed it leave a like down below comment what you want to see next subscribe because i'm posting every week and i would massively appreciate if you guys could help support the channel and yeah that's basically it really hope you guys enjoyed it and i see you guys next time [Music] [Applause] [Music] [Applause]
Info
Channel: PedroTech
Views: 55,788
Rating: undefined out of 5
Keywords: computer science, crud, css, databases, javascript, learn reactjs, mysql, nodejs, programming, react tutorial, reactjs, reactjs beginner, reactjs tutorial, typescript, react js crash course, react js, node js, express js, pedrotech, traversy media, traversymedia, clever programmer, tech with tim, freecodecamp, deved, pedro tech, tic tac toe, react tic tac toe, react project, react resume projects, full stack, full stack react, react authentication, react chat app, getstream, react api
Id: Iw1YmBoOYb4
Channel Id: undefined
Length: 146min 16sec (8776 seconds)
Published: Wed Mar 09 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.