React / Typescript Tutorial - Build a Quiz App

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome to this tutorial I'm too much wave infarct a developer and instructor from Sweden I created this tutorial for free code camp and free code camp is great I also want to tell you that I have my own YouTube channel baiban fault but for now let's get started with this alright this is the quiz that we're building in this tutorial so we can start and we get some questions here and we have 4 different choices to choose from so if we press here you can see that it showed me that I answered incorrectly and it also showed me the correct answer and then we can move on through the questions here and this is all built with react and type Swift so that's what I'm going to show you in this tutorial this is the finished application alright so let's get started we're going to bootstrap application with create direct app and we're going to set it to use typescript so if we check the site here create - react - app dev we can see that they have they have an option for adding typescript so we can use MPX create react app and the name of the application - - template and typescript and this will install everything with the typescript support for us so we can do that so let's go inside of our console here it and then we type in MPX create - the react - app and then our application is going to be named the react - quiz in this case we type in - - template and type script and we wait for it so this will install everything with types of support for us so we just have to wait and it will be boot cut for us okay that went smooth let's see what we've got we have a react with folders we can navigate inside of that one CD react - quiz and then I open up the code editor we're going to clean up or product a little bit as you can see if we look in the folder here we have some files here and inside SRC folder we can actually remove some stuff that we're not going to need set up tests serviceworker the logo the index dot CSS the app dot test dot t-- sx and the app dot CSS remove those files like that and then we're going to do some refactoring here in the index dot TX file we can remove this one where we ins where we import the CSS file you can remove this one to import a serviceworker and also remove it down below here and this should be it save the file and then in the apt of tsx file we remove the CSS import and the logo and for now we're just gonna say quiz inside of here and do some more formatting and save it then we're gonna use star components to stall this one I'm going to start it at the end of the tutorial so we're just going to build the functionality first but we can install the dependence for the star components and we can install it by typing NPM I style it - components and as this is in typescript we're going to do this application we also have to install the types for this one and we can grab those ones from at types forward slash style - components like that so we first installed the style components library itself and then we install the types for the style components and we do it in one go so press ENTER alright then we can just start this up to see that it works NPM start and we can go to localhost port 3000 and you can see that it says quits here and that's great we know that it's working so localhost colon 3000 that's the dev server that this one creates for us and you can see you can also just click here and it will open up in your browser hopefully all right so that's the dependencies we only need to install style components for this one as a dependency but we have to do some more stuff here first we're gonna have this nice little summer background image and I grabbed that one from unsplash.com and I found this image down below here it's not to add none that has photographed this image so that's the one I'm using so we can just download this one or if you want to use another image you can use that also so if we check out this image it should be in the download folder and you can see I actually have two of them here because I've already downloaded it before so let's go inside the code editor again and inside the SRC folder we're going to create another folder that we call images may be overkill for this one as we only have one image but I like to have a good structure on things so images and then we grab this image and drag it inside of there and I can actually rename it also because it has this strange long name we keep the name of the guy der has taken the photo all right so that's the images we also got to need a couple of Google Forms so go back to the web browser I opened this one up for us I'm going to use the form that's called catamaran I don't know if I pronounced that correctly yeah I'm gonna use the weight of 700 so select this one I already selected it here and I also gonna use a form that's called fashion eight in line these are the two fonts that I'm going to use so I've selected that one also so you can browse the fonts you can search for them here and then you add them and then we get this embed link here so copy this link go back to our code editor and we're going to navigate inside of the public folder and we have the index dot HTML and in this case we're going to paste it in here so we import it in this index dot HTML this is the file that is run when the application is built so we can import it here just like in a regular HTML file save it and this will make sure that we have those fonts all right so that's the fonts I can close this once and then we can just briefly check out the API that we're going to use for the questions so I found this open trivia API as you can see we can configure it we can select which category we want I'm going to use the ANA category we can select difficulty I'm not going to implement to select difficulty in the UI but I'm going to implement it in the app itself so you can change it in the code and we can also change to have multiple choice or true or false we're going to have multiple choice and we're going to use the default encoding and if we click generate API URL it should generate the URL for us up here so this is the URL and this will give us a JSON response with the questions and the answers as we just get this object it will be really is it a sheet if you want to do that because you can always check the questions and answers in the code because if we want to make a serious quiz game we probably have to create the proxy API or already use an API that won't show us the answers in the client so we have to make a request to a server and then it will get a response with answers and stuff like that but in our case for example if you have a react dev tools you can just check the state and you will see all the questions there and the answers so it's a very simple implementation of a quiz game and that should be it for the setup let's move on to create the logic for the application and then last in the tutorial we're going to create the UI the design for the application ok make sure that you have the application running by typing in NPM start in the folder that we created we'd create drag tap and it will hopefully show Wis for you and it's also a good idea to have the console open so we can open that one up like that and then move back to a code editor the first thing I gonna do now is to create a couple of new files and a folder because we are going to create a component for our questing card so inside our SOC folder I create the new folder that I call components and then I'm going to create a file inside of that one that I call question card not TSX capital Q capital C question card TSX and we can just scaffold this one out for now so we import react from react and then we create the Const question card and an error function and from now we can create a div that says question court and we export default question card do some more formatting and save it so that is our question card component we're going to come back to this later and then inside of the SRC folder we're going to create two more files so first we have a file that we call API dot TS capital letters on API and then we have another file that I'm going to call utils dot TS like that so the API file is going to be used where I create the logic for fetching data from the API and the utils file is just going to keep a small function that we're going to use to randomize the answers to the questions alright and we're going to come back to those also and then later we're going to create more files here because when we create the Styles with a start component I like to have the Styles in a separate file so we're going to create separate files for those also but we do that when we've created all the logic for this quiz game so let's start off in the app dot tsx file this is going to be the main file for our application and if you want you can change this - an error function I like to have error function but this is highly what we call it highly subjective if you don't like error functions you can use regular functions so it's okay this is the main component in our application so if we start scheduling this one out we're going to have one function that we fire off when we start the quiz so cost start trivia or start quiz start trivia I think that is fun this one is going to be async because we've got to make the API call from this one so we can already know marked it with async so we leave it empty for now then we're going to have one function that we're gonna trigger when the user selects an answer so const check answer equals this one is going to take in the event like this and you can see that it complains you know because this is typescript they're telling us we haven't specified the type for this one so it's implicitly set to an e and we should set a type for it so the event is going to be a mouse event and we can specify it even more so we specify two HTML button element and we end it with a angle bracket like that something like that and of course we need to have a colon here also and as we're in react I guess we have to tell it react dot Mouse event also like that so ragtop Mouse event and then we specify it even more by telling it it's from an HTML button element so that's how you type this event now we're gonna have a function that will trigger when the user click for the next question so const next question equals and in this one we don't actually need the event so we just create an empty our function like this this is all the functions that we need for this trivia and of course we're going to come back to them in a second but first we're going to scaffold out or JSX here in the return statement so we wrap it in a parenthesis first like this and then we have the right that's called at now we're gonna rename these ones also later when we create the star components but for now they will be dibs with class names and first we're gonna have an h1 tag with a header for the quiz and we call it react quiz like that then we're gonna have a button to start the game so we create a button with a class name pull start and we set the onclick handler to the function that we created start trivia like that and it can just say and you can just say start inside of it so that's the button then we're gonna have a paragraph with a class name of score and this is the one that's gonna hold the score so for now we're just setting score like this then we're gonna have a paragraph with a class name that is telling us loading questions you can repost implement a spinner or something if you want to do that instead and then we're gonna have our question card so we can import that one up here I mark it with components and import question cord from it's in our components folder and then we have the question corn like that so down below here we create the question cord like that and the last thing we're gonna have is a button below everything of this that is used to click to the next question so button class name equals next and for this one we have an onclick handler next question like that and we can just well next question do some Auto formatting so you can see that we're using the next question and a start trivia here this one here is going to be sent in by props to the question cord component so we can create the question cord component now so let's go inside the question card tsx file just as before we create parentheses here we can make an implicit return on this one so we don't have to have a return statement and as we were in typescript now we have to type the props for this one so we create a type to pull it props you can call it whatever you want it doesn't need to have the name props first we're gonna give it the question and this one is going to be a string the question is always going to be a string then we're going to give it all the answers and the answers it is going to be an array of strings so string array this is how you type an array of strings then we're going to give it a callback and for now we can just set it to an E and we have the user answer that's the answer that the user is going to give us it's also going to be a string we have the question number it's going to be a number we're still number like that then we have total questions that one is also going to be a number so these are the props for this component but how do we specify it to use these props first of all we have to specify this one to be a functional component so just after the name here we have a column and from react we have something that's called FC so doped FC these are the types from react itself so it will tell time trip that this is a functional component and if we want to specify props we do that inside of angled brackets like this so we tell it that we want to use these props that we created up here and none just as usual we turn the structure of the props so we have the question we have the answer you can see that we get this nice auto completion here where it tells us what we've got we have the call back we have the user answer we have the question number and we have the total questions are going to do some Auto formatting here because I have this insanely large font because I want you to be able to see what I'm typing but it's hard to work with it actually so these are the props that we have now and now we can use them inside or or component so this div is going to be a rapid if I'm gonna create parenthesis here again so we have the rapid Eve we have the ending parenthesis remove some stuff there so this is the relative we're going to display the current question that we're on so you can do that in a P tag with a class name of number and then we can type out question : and then from the props we're gonna grab the question number like that and then we do a forward slash and then we grab the total questions like so because we're in JSX now so when you want to grab a JavaScript variable or create the JavaScript expression we do that inside of curly brackets alright so that is going to indicate what question the user is on and then we have the question itself and in the response from the API we're going to get some HTML in react we have something that's called dangerously set inner HTML that we can use when we want to render out some HTML and it's called like this because it is dangerous to use because you never know what can be injected there in our case we know that it's safe so we can use it here so we create a pit tag and we use dangerously set inner HTML and we have curly brackets then we have the new set of curly brackets because it's an object and we have underscore underscore HTML and we're going to give it a question now it shouldn't be the question number it should be the question like that alright then we're gonna have a wrapper div for all the answers to the question we're going to map through the answers because we have all the answers in this prop here it should actually be called answers with an S and not answer we can change that one answers with an S so down below here in the wrapping div we create curly brackets and we have the answers dot map so we met through them we have an answer like that we create an inline arrow function we can use implicit return here also so we create parentheses and then we have a wrapper for our button to create another set of divs and inside of the error created bottom it's gotta be disabled depending on if the user has made a choice if the user has answered something so we set to disabled equals user answer this one is going to be a boolean so it will be disabled if this one is user I'll say yeah I set it to a string you can see that typescript complains you know because I said it's the string it will complain we will make sure that this will get a true or false value later so we have to change this one now so it should be a boolean instead you can see that it won't complain anymore so this is one of the great strengths with tight script it will tell you when your code if you do something wrong and you can correct it before the bug even happens all right then we have a long kick Handler on this one and this is going to call the callback like so we close it I'm gonna have some text for the button also and this one is also going to get the text in HTML format so we create a span and dangerously set inner HTML equals curly brackets and we have the object with another set of curly brackets underscore underscore HTML and we give it the answer in this case and then we self close to spam do some Auto formatting see that everything works I think it is working yep save the file but now you can see inside of the app dot tsx file if we go back to that file so you can see that it complains now because it wants to props and we're going to give it to props also but first I'm going to create the states that we're gonna use for this application and we're gonna have six of them actually because I'm gonna spit them up that's great with hooks now you don't need to have one big state we can have a few of them instead so up here first we import use state like that and just down below here in the component at the beginning we're gonna create our state's first we're gonna have a loading state so const loading and set loading like that and we use stale we set it to false as a default then we're gonna have the questions like that and set questions and we use state and we give it an empty array for now we're also going to specify this later give it a type but we can't do that yet because i'm going to create that type when we create a function for the api then we have a state with a number and set number and this is going to be the number that the user is currently on the question number so use state we're gonna start at 0 then we're gonna have a state for the user answers and set user answers like that and use stale and we give it an empty array as initial value and then we're gonna have the score and set score and you still and this one is 0 as initial value and then i also gonna have one it's called game over and set game over so that we can keep track on when the game is finished so you stayed and we set it to true initially okay so let's give this question card its props first we have the question number and this one we're going to get from number but we're going to add one because the number is going to be used for the array and the race starts at zero and we don't want to start our questions with a zero so we add one to this one because that will make the first question to have the number one okay then we have the total questions and for this one we're going to create a Const up here Const and we have capital letter total underscore questions equals ten and this one is because it will be easy to just change this for us if we want to modify the total questions so total questions is going to be the total underscore questions like that then we're going to have the question itself and we're gonna grab this question from our question state and we have the question state here it's gonna be an array of questions so if we want to give it a current question we can do that with questions and then we grab from number and then we give it the question itself you can see it complains now because so now typescript doesn't know that it exists with complaints here to us then we're going to give it two answers and we have our answers also in the questions number and in a property that's called answers like that and then we're going to give it the actual answer from the user so use your answer equals and then we check if we have some user answers we create a toner operator and if we have some answers in the user answer state use your answers we can grab the correct answer by specifying the number otherwise we just give it undefined like that and you can see here yeah it should say use your answers and this one will complain out cause I realized that if we go back to the question cord you can see that tell this one that it's a boolean it's actually not so we set it to Annie for now go back to our app dot TSX file and you can see that it won't play now and the last one we're gonna give it is the callback and it's going to be the shaky answer like that and now you can see that it won't complain here because we're giving it all the props it will just complain here because it doesn't know that these properties exist but we'll fix this soon so I think we have everything set up now actually and we can move over to the API dot TS file and create the function that will grab the data from the API so we export Const fetch with questions like that and this one is going to be async and we're gonna have a couple of parameters here because we want to be able to specify how many questions that we want to grab so we can create a parameter amount it's going to be a number and then we have another one that we call difficulty and this is going to be easy medium or hard because we can grab these from the API so we should be able to set it here how do we specify this because it can only be easy medium or hard and in typescript we have something that's called an enum so export enum we call it difficulty like this and we can specify the constants inside of here we have one that's called EC and it's going to equal EC then we have the medium one and it's gonna of course equal medium make sure you have a coma after these ones also and then we have hard and it's going to equal hard and I actually want to have a capital D on difficulty so we can specify this parameter as the enum difficulty alright and this will make sure that we only can use these values and it won't accept anything else that way we won't make a mistake of typing something like this for example because then the end point won't work so that's the parameters for this one then we want to specify the return type it's going to be a promise of yeah I can actually remove this one for now because we're going to console.log out what we get from the API first and then we can see what type we're going to specify this one so inside here we create a Const with the endpoint I create a template literal with backticks so HTTP colon forward slash forward slash open TD be calm for a slash API dot PHP question mark amount and then we have an equal sign and then we can grab this variable here amount so we create the dollar sign curly brackets and give it the amount and this one around typing in now is of course from the API so we could of course just also copied it then we have an ampersand and we're gonna give it the next variable here so difficulty equals and then where the dollar saw in curly brackets and we give it the difficulty argument and the last one we have another ampersand and we set the type equals to multiple so as you can see can configure this as you want in this case I'm just making sure that we can change the amount and the difficulty but you could change the type and stuff like that and really customize it how you want it to be we end it with a semicolon alright so that's the end point then in a cone star called data I'm gonna wait because we are going to hit that endpoint now so I await and then I have a parenthesis I await again I get a lot of questions on why I'm using double awaits and that's because first we await the fetch itself and then we're going to wait when we convert it to JSON so wait fetch parentheses we give it the endpoint like that and then here we have dot JSON and we call that one so this will await the fetch itself and then it will await when we convert it to JSON and for now we're just going to console log out the data like so we're going to come back to this one go back to the app dot TSX file and I'm actually gonna comment out this one for now so we don't have an error and up here we can import that function that we've created so import fetch quiz questions from dot forward slash and we have it in the API dot TS file like so and what I want to do now is to try this function out to see what we've got so we have this function here fetch quiz questions really hard to say for me and we can call it here console.log fetch with questions like that and we need to give it two parameters now you consider it complaints expected two arguments but got zero so this is also great with typescript it's telling us all the time if we're doing something wrong so first we're gonna give it the total questions and then we need to give it easy medium or hard and if you remember in the API dot TS I'll we created this enum here that I also also export so that means that we can import this one in the app dot TSX file so I'm going to mark this one with types and I import difficulty from dot forward slash API like so and that means that we can use it here so in our console log as the second argument from difficulty we're going to grab the easy one save it go back to our browser you can see that we have everything here now and here is the response you can see that we have a response code of zero and we have the result so this is what we care about here the 10 questions here and now we can see the structure of the object the question object here by looking at this one here we can actually create the typed for this one so we have a category the correct answer and difficulty these are all strings then we have the incorrect answers in an array and then we have the question and the type so let's move back to the code and inside of the API dog TS file I'm going to specify the type for each question so type I'm going to export this one also export type question equals it's always good to export stuff like this because you never know when you need it in your application so first if we go back to the browser you can see that very category correct answer difficult to incorrect answer question and type so now it's just a matter of specifying this here category this one is going to be screen we have the correct underscore answer this one is also gonna be a string we have the difficulty it's a string we have the incorrect underscore answer and this one is going to be an array of strings so screen and an array we have the question itself it's going to be a string and then we have the type it's also going to be string but one thing I want to do here also because I want to modify the stay that I get back here because in this case we have the correct answer in a separate property and we have the incorrect answers in a separate array I want to have them in the same array because what I want to do later is that I want to map through this array and create the answers in the UI in the JSX so it's easier to have them in one array so we can have both the correct answer and incorrect answers in one array instead so i'm going to add a property in the object that we returned here from the api and we also have to specify that with type swift of course and how do you do that well I'm going to create another type IX port type and I'm going to call it question state so first I grab the question that I created here but I want to add something to this one so I create an ampersand and then I have an object I'm going to create a new property that's called answers and this one is going to be an array of strings so like that you saw more formatting so this will use the types from the question but add this property to it and it will create this question state type instead so we all good to go now we can return the correct data here in the fetch quiz questions there is actually misspelled here questions it should sell and I need to change it in the app also like so and also here yeah something like that go back to the API dot t-- s file alright so we know that we get our data then we have to return some things so our return and from the data dot results I'm going to map through all of them and add this property that I talked about it's a map we have a question and now we can specify it as a question from our type question like that we make an implicit return we have a pair of curly brackets because we return on object and then we spread the question we want to use all the properties that we get from the question and you can do that with es6 syntax that's called spread so that's what we're doing here and then we add the new property of answer and there's actually one more thing I want to do because I want to shuffle the array here otherwise the correct answer will always be on the same place and that's why I created this utils dot TS file so move inside of that one and we create another small function here export Const shuffle array and this one takes in the array and it can be of any type in the array for this one we have an error function so this array that we give this function I'm gonna create a new array by spreading it inside of a new one this is also a year six intact spreading inside of here creating a new array and then I use sort give it an inline error function and use math dot random minus 0.5 do some water formatting and this is kind of a quick fix for creating a randomizer function it's not completely accurate but in our case it will do so this yeah this have to do for now this is not a tutorial about creating random functions so this will do the trick for us this will do the job so save it and go back inside the API dot TS file and up here at the top we can import this one so import shuffle array from dot forward slash and utils like so so go back below here where we create the object and inside the answer property I'm gonna call the shuffle array and give it the array that I want to shuffle so yet again I use es6 syntax I create an array I spread from the question dot the incorrect answer you can see here typescript gives us all the properties that's available for us so the question dot incorrect answer and then from the question dot correct answers correct answer so we spread all the incorrect answers and the correct answer and then we shuffle it with this function here do some more formatting and it will look something like this yeah and before we do anything this one should be in correct answers right so I keep forgetting these SS I don't know why but I keep forgetting them make sure that it says incorrect answers with an S and also change the type to that one save it and this one goes also here this property here should be called answers with an S yeah because it answers here also so keep forgetting those SS add them to these ones otherwise it won't work alright save it go back to the browser reload it and you can see now we have a promise here but we can see that it's resold and if we look at the question here you can see that we have the new property with answers here so you can see that the correct answer for this one is bull we have that one inside of here and the incorrect answers is bad horse and snake and we also have these ones so this is exactly what we want now we have an easy way to map through all the answers when we do that all right so let's get back inside of the code this is the API or TS file it's finished now and also the utils of TS is finished so back inside the app dot TSX file so in the types we're also going to use the question state the question state that's the one that we created we import that one also here and now we can set this one is going to be an array of the type question state so you can specify that one here inside of the angled brackets question state and an array like that my script will know because we're sending this to an empty array it can't really know what this is going to be but but specifying like this we tell type if that this is going to be an array of question state so we have to create this type for the answer object also just below here we create a new type we don't have to export this one because we're not using it in another component answer object equals and the answer is going to have a property with a question it's going to be a string we're going to have the answer and this is a string we're going to have a correct that's the boolean like so and then we have the correct answer and it's a string so the correct will tell if the user answered correctly and the correct answer will have the correct answer and then we have the user answer here and we will start the question and this is good to have a complete object like this because if we for example want to extend or game and show all the questions in the end when the quiz is finished we have them nicely in this array that's called use your answers we're not really going to do that now but I created it this way so you can kind of extend from here if you want to do that now we can specify this user answers so we create angle brackets and answer objects and an array so then we have all our types for the state's save it and just make sure that it still works it does so that's great so we're going to implement the stork trivia function now so that we can start a game so inside of that function we have to do some stuff here first when we click the start button we're going to trigger the API fetch and that means that we're loading something so we're going to set the loading to true that's the first thing that we do and we're also going to set the game over to false because when we start a new game it's not game over so when we done that when we set the loading and the game over we can hit the end point so we create a Const new questions then we're going to wait and we call the fetch quiz questions and we're going to give it to two arguments that it needs it needs the total questions and just as before we give it a difficulty dot EC as the second argument all right so that will grab the new questions and put it in this comes here so when we awaited this one and we have all the questions we can set the questions with the new questions like that and hopefully we have all the questions in this state and in this tutorial I'm not doing an error handling so you could of course use a try or catch lock and if you want to catch the error or something like that this video is already getting long so I won't go into that here but you should of course always do some arrow handling if you have an error all right then we also got to set the score to zero because we're starting from scratch now so it should be reset and we set the user answers to an empty array so we can do setting everything here it's a set number we also said in that one to zero and then when we've done all of this we hopefully have or questions in or stayed and everything is working then we can set the loading the force because we're not loading anymore and this is it for the start preview function so save it go back here and click start you can see that we get the promise here but that's because we're console logging it out here we can remove this one here and actually just console.log out the questions instead so go back to the browser press start you can see that we have all the questions inside of here and you shouldn't worry because you may wonder why whoa if we rerun this a lot of stuff here but that's fine there's no performance issue here that's because we have a lot of these states that will trigger a render but it will only render stuff that is new for each render so you shouldn't worry too much about that especially not in a small app like this all right so we know that we have our questions in the state that's fine it's working really nice but for now also you can see that just as loading questions we want to display the questions and the answers here also so we can modify our JSX here so first this button here to start the game is only going to be displayed if the game is over or if the user has answered the last question so we create curly brackets we check if game over or we have double pipe user answers dot length equals total questions then we know that we're on the last question and then we're going to display this button it can get a little bit messy here now so we have parentheses around that one otherwise we return null we have the ending curly bracket there like so I think and you could also do a regular short-circuit without this Turner operator if you want to do but I think it's ready to return at least null and as you can see now it displays the button but not now when we press it so that's working okay that's the start button and then we want to show the score we only want to show the score if we're not in a game over mode for this one so curly brackets not game over we have another Turner operator and otherwise we show null and we have the end curly bracket like so and the loading questions is only going to be shown when we load something so curly braket loading like so and no yeah it may be better to just have a short circuit I can do it like this for this one so if it's loading is going to show this one save it and we can see what we've got so we have start the next question we start you can see that the loading was showing and we show the score so this is working also go back to the code now we're going to bring back the question card and the question card is only going to be shown if we're not loading and if we're not in game over so we created curly brackets not loading and not game over yeah I do a short circuit here a little bit messy here again something like that do some more formatting so if we're not loading and if it's not game over we're gonna show the question card save it go back to the browser start you can see that where the question and the answers here that's sweet now we have the next question button also but we haven't implemented those functions yet all right that's the question card and then we have the next button and this one is only going to be shown if we're not in a game over and we're not loading the user answers dot length equals number plus one and by doing this we just want to show the next question when the user actually has put in an answer so that's why we shake it here if the user answers dot length equals number plus one so we don't show it if the user haven't given us an answer yet and the last thing we want to check if we're not on the last question so number not equals total questions but we have to modify this one also because we have to set it to minus one and then I have a question mark parenthesis this is really messy here now I'm gonna move off the bottom inside of there and down below here : and now yeah it should just be two equal signs there of course and do some order formatting and I think that this will work go back to the browser yeah so now it's not showing because we have to give an answer first before we showing that one yeah and it's telling me that it should have a key prop here we're going to fix that one also and that one is in the question chord because here where we map through this ones we should have a key and we can give it the answer as a key and this will make this arrow go away or this morning all right so this is working now go back to the app dot tsx we're going to implement the other functions now and then the game will work and then we can move on to create the star for this one so inside the check answer first we're only going to run this function if we're not in a game over so if not game over then we get the user's answer Const answer equals and get that from the e-dot current target dot value because this is when we press that button here so you can see that we calling this callback on click and that's why we also have to set this value on here it's a value we give it the answer like this otherwise we won't be able to read the values it's very important to set the value also on the button here on the question cord in the question core component like that go back to the app dot TSX so from e dot current target dot value we'd get that value and that's going to be the answer then we're going to check answer against the correct value or the correct answer so cons correct equals from questions we have the current number that's the question that we're on we have the property that's called correct underscore answer and we check if that one equals the answer then we know if if it's correct or not so this will give us true or false add score if answer is correct so if correct set score and we have the previous score and we add it by one like so all right so that's if it's correct then we add to the score and then we're going to save the answer in the array of answers here and we have this answer object we're going to give it a question answer correct and correct answer so that's what we're selling here so save answer in the array for user answers something like that comes answer object equals and we create an object question the questions number we grabbed the question and then we have the answer then we have the correct and this is also es6 syntax if this one is the same this is exactly the same as typing out answer when these two are the same we just need to type it out once like this and then we have the correct answer and from questions and the number we have the property that's called correct answer it's a water formatting and this will make sure that it raises object with the data about the answer and then we need to put it in the answer array so set user answers we have the previous state and we create a new array spread out the previous and we give it to answer object or a format it and save it and this should be it for answers go back to the browser see that it works reloaded start yeah you can see the next question is showing up also but is not working now because we haven't implemented this function but it seems to be working so we just have to implement that function also and then we have a fully working game but it will look like crap because we haven't styled it yet so we have the next question function here move on to the next question if not the last question so we have to check if we are on the last question the cost next question equals number plus one because the question recurrently on is the number and then we add to one and then we can check if this is the last question or not so if next question equals total questions we know that that one is the last question because total questions is always going to be one number ahead of the number because we're using this for the array that starts at index zero and this one doesn't do that so we have to add one so when we check the next question with the total questions that will give us the answer if we're on the last question and if we're on the last question we set game over to true like so else we're not on the last questions we can set the number to the next question like so or a format it and save it and go back to the browser reload it just to be sure and start select an answer which of the following was not one of the Magnificent Seven oh I really don't know actually next question and you can see it will move through the questions we can't see the correct answer now because we haven't styled it but it seems to be working let's see what it does when it's on the last question you can see it displays the start button when we're on the last question and it's not displaying the next question so we can restore the game and it's working quite nicely I think but as I told you we can't really see if we put him the correct answer because we do all that stuff with a styling and that's what we're going to do next we're going to use star components to style this quiz all right before we move on with the styling for this one I'm gonna fix these types because I forgot that we had these any types here and if we can fix it we should do that so we can type this correctly and we're going to change this call back and the user answer so for the cool back we already have the types for that one in the app dot tsx file if we go down here to that function this check answer function we are already typing this one here so you can just copy this one like that copy that one go back to the question card or tsx file and replace the anny with this one instead and we're going to return void for this one we're not returning anything so we can specify it as void so that's the callback and the user answer we actually created the type of this one also in the apt of tsx file we have this answer object I think I said that we didn't need to export this one but we have to export it because we can use it in the question card now to specify that type so add an export to that one and then we can import it in the question card or tsx so add an export save the file and then go back to the question card or tsx and up here we can mark it with types so import answer object and we import it from dot forward slash app something like that so we have the type here now for the user answer so instead of an e we can use answer object but it can also be undefined so you create a pipe and specify it as undefined like that save the file and there's also one more thing we have to do now because down here this one disabled it wants a boolean and this one is not a boolean now so if we want to convert this one to a boolean value we can use double Banks double exclamation marks or we can specify it like this with a ternary operator if we have the user answer we set it to true otherwise we set it to false so it's up to you you can use whatever you want but just make sure that you give this one a boolean value otherwise it won't work so this is it this is all the types now we don't have any any type now except in this utils function because this one can take an array with an e value so make sure to save the files and I'm also gonna check so that it works go back to the browser reload it and it still works and that's great so that's the types let's move on with a styling ok we're going to give this quiz some styling but first we have to also make sure that we display the score I forgot that one so we have this state with scores move down here to the JSX in the app dot TSX component just somewhere here yeah here well we set the score we're actually not showing anything there now we're gonna add that one here so we have curly brackets and we show the score like that this will make sure that we show the score to the user and you should be able to see yeah yeah I got a score one there yes you can see it it's displaying nice alright so we're gonna create a new file now we're going to create some styling for the app dot TSX file first so inside the source folder the SRC folder create a new file F dot stars dot t-- s and we're going to import some stuff from star components so import styled coma and then with the structure out create global style like that from dot style components so style is the regular thing that you import and we're also importing create global style I think it is self explaining we're going to create some global styling with that one that's the first thing that we're going to do but first we also want to import our background image be the image you can call it whatever you want from dot forward slash images forward slash and then we have that I really don't know why it can't find it yeah and this one is complaining because I removed the test file before I think that shouldn't matter but this is strange I think we just created TS ignore for this one from now something like that I think it will work we'll see if it worked later so export comes global style you can call it whatever you want you don't need to call it global style but we call the great global style with double backticks and we can create a global styling we set the HTML I'm gonna set the height to 100% on that one and just as usual when I style stuff like this there are some room for optimization I think I just did it Styles really quickly so there probably will be more effective ways of doing stuff here but I mean a summer vacation mode now so this will probably be one of the last videos before I take a well-deserved vacation so that's why I actually didn't think I was going to do this before the summer but then I felt yeah why not so that's why I created this one all right so we have the body we set the background - image to the URL and then we can grab this URL with dollar sign curly brackets biggie image like that and then we set the background size to cover i set the margin to zero the padding is gonna be zero and 20 pixels i set to display the flicks and justify content to sender so that's the body and then i have an asterisk I'm gonna set the box sizing what sizing the border box and I'm also gonna set the font on every element on this one so fun family catamaran and Sam's reef as a fullback font all right so that's the global styling I'm actually going to import that one in the app component now to see if this background image works so go back to the app dot TSX file and up here I mark it with styles I import global style from code /f taught styles and then when you create a global style with star components we get the regular come volunteer so we can use that one down in the JSX you can put it somewhere here at the top so I create a fragment because the SX can only return one element I close it here and then we can use the Globalstar component like this do some Auto formatting and save it go back to the application yeah and the image worked I don't really know why it complained there so if it complains just add a little comment here that I created the comment this one out I don't really know because it worked in my application when I created this example so don't really know why but that's the global styling and then we can do some styling in the app itself so export Const I'm gonna create a component that I call wrapper style dot div double backticks it's going to be displayed as flex flex direction it's gonna be column and align items is going to be centered like so then I want to style the P tag in this wrapper so I created a forward error and the p2 just style the P tag in this app wrapper I don't want it to be styled on all the P tags so I set the color to white so that's the P tag then I'm going to have a class that I call score and that's of course the score table I set the color there also the white we could of course specify some CSS variables for the colors if we want to do that that's one way you can optimize this CSS I set the font size to 2 or M the Morgan is gonna be 0 on this one all right so that's the score class then we have the h1 tag and this is going to be this one up here that's going to be the actual logo that I'm styling with CSS all right so the font family is gonna be fascinate inline not impact in line like that then I set the background image and this one is going to be the linear gradient it's a linear - gradient and inside it's going to be 180 degrees unrelated egg I said the first evaluative white and the second one is going to be 8 7 F 1 FF and to be able to show this linear gradient in the font we also have to set the background size 100% and the background - kit is going to be text then we can all all the WebKit stuff here for this one so WebKit - background Kip it's gonna be text WebKit - text - Phil color is going to be transparent and we have the moss door - background clip it's gonna be text and we have the most text - fill - color it's gonna be transparent double - maybe all right now we're gonna have some drop shadow on this one so we set the filter to drop - shadow and two pixels two pixels and the color is going to be 0 0 8 5 a3 the font size is gonna be 70 pixels text the line it's going to be Center and if Morgan is gonna be 20 pixels on this one okay we're not really finished yet but we can import these Styles inside of here in the app dot TSX file just to see that this one works so we import the wrapper and below here we have to change your JSX because now instead of this deep with class name app we're gonna use the wrapper component and make sure to also close it down below here save it go back to the browser and you can see that it's not quite working here and I don't know why I think it's those I thought stars I think maybe this one's should be just one and I also want to set the font weight 400 on this one save it go back yeah and now it's working so there's a little bit of trouble doing stuff like this as you can see there's a little bit of special syntax here to get it to work if you don't like to do it this way you can save that logo as an SVG file instead and that will also work just fine all right then we have a couple of more classes here so we have the start and the dot next class I'm going to set the cursor to a pointer I'm gonna set the background on these ones as a linear gradient her own 80 degrees on that one also I set it to white and then the second color is going to be ffcc not in one so that's the start on the next button we set the border to two pixels solid and the color is going to be d three eight five five eight like so I'm gonna have a book shadow zero pixels five pixels ten pixels and then I set there RG be a 0 0 0 and 0.5 no 0.25 on the book shadow I set the border radius to 10 pixels and the height is gonna be 40 pixels Morgan is gonna be 20 pixels 0 and the padding is gonna be 0 40 pixels like so and then I want to do some special styling on the start button so max - width is 200 pixels order format it and save it go back to the browser and this should be it hopefully start you can see that the next button is also style here but we're not styling the actual question card now so that's what we're going to do next right so inside a components folder we have our question card to create a new file question cord dots tiles the tears and for this one we import style Rome style components then we export Const wrath per stylist deal you can see also that in this tutorial I just created a wrapper and then I have regular classes you can of course create a style component for each little thing if you want to do that but sometimes I think it's overkill so it's just enough to have this wrapper and I create classes in this case I'm also going to have a bottom wrapper on this question cards so I create two components for this one but it's fully legit to just have a wrapper and then you have your classes inside if you don't want to create a start components for every little thing in your application all right we set a max width on this one to eleven hundred pixels I set the background to EB F e FF I set the border dash radius to ten pixels I set the border to two pixels solid and the color is going to be 0 0 8 5 a3 the pairing is gonna be 20 pixels and I have a book shadow on this one also so book shadow zero pixels 5 pixels 10 pixels rgba 0 0 0 and 0.25 and it takes the line it's gonna be centered right then I start the P tag for this one we're gonna set the font size to 1 RM like that so that's the wrapper component then we have the bottom wrapper so export comes bottom wrapper equal style give and this one is actually going to take in some props and how do you do that in star components well we can create a type here for example type bottom wrapper of props and it's going to take in two props correct that's going to be a boolean and you see clicked that's also going to be a boolean all right and to use these props in the star components we create angle brackets here and we specify the bottom wrapper props and then we have double backticks then we can go on just as usual here and on this bottom wrapper I'm going to set a transition I'm lazy I'm just turning it to all zero point three seconds and ease the hover is gonna be I set the opacity to 0.8 when we hover over the button and now we have the burn on itself Sabourin i set the cursor to a pointer the use of select it's gonna be none I don't want the user to be able to select the text the font size it's gonna be 0.8 aureum the width is 100% the height is 40 pixels the margin is 5 pixels and zero on this one then we're going to set the background and this one is going to be a nested ternary because we want to change the background depending on if we're showing the correct answer or if the user put in the wrong answer so we set the background and in star components we can grab the props by dollar sign curly brackets and then I can the structure of them like this so we have the correct prop and the user clicked prop and then we have the inline function here so first we're going to check if correct if that one is true have at owner/operator then I set the linear gradient to 90 degrees and the color is going to be 5 6 f f/a 4 as the first color and the second color is going to be 5 9 bc 8 6 like so so that's the first linear gradient so that is if it's the correct answer then it's going to show in green then we have the colon and then we have a nested Turner operator here so if not correct and the user clicked so the user clicked is going to tell us if the user clicked on that specific button so we have a nested ternary operator here so we have another question mark and I can actually just copy this this one here paste it in and I can change these values here this one is going to be FF 5 6 5 6 and this one is going to be C 1 6 8 6 8 and we add in the last one here so : we had the last linear gradient this one is gonna be 5 6 c c FF + 6 e a FB for do some auto formatting but I have some mistake here yeah just because that question mark shouldn't be there or a format it and that's the background then we have some few more properties to set here I'm gonna set the border the three peaks are solid white I'm gonna set the box shadow one pixel - pixel zero pixel rgba 0 0 0 and 0.1 all right almost finished here with a styling border-radius is going to be 10 pixels on this one and the color is going to be white and the last one is the text shadow zero pixels one pixel zero pixel rgba 0 0 0 and 0.25 and all for merit so that's the styling now we just need to implement it in the component itself so optimize it if you want to do that at least it works now but it may not be the most optimized CSS so go back to the question card dot TSX file and up here at the top we first gonna import our Styles import wrapper and bottom wrapper from dot forward slash question car Styles like that and then we have to modify our DSX here a little bit so first we have this rapid if that of course is going to be the wrapper make sure to end it with the wrapper also then there's nothing here to change this one is the bottom wrapper so this one is going to change it's going to be the bottom wrapper and if you remember we're going to send in two props to this one also because it's complaining now you can see it wants two props so the key is correct there that's fine but we're going to add in the props here so correct that's the prop we're gonna check the user answer and here I'm using something that's called optional chaining in typescript so I create a question mark dot and the correct answer and I check it if that one equals the answer we should have triple equal sign so if I remove this one we don't actually know if we have a value here but if we use the question mark this one will not throw an error it will make this on the front if you don't have an answer here so that's why I'm using optional chaining then we have the user clicked so user answer yet again I use the optional chaining dot answer equals answer or a format it so if we don't have this one here it will throw an error if we don't have a user answer but by specifying like this it won't throw an error and I think this actually should be it so save it go back to the application with tryout start and yes we have our question here that's what okay that was right you know that one all right the next question so as you can see I answered wrong but it's given me the correct answer here so everything seems to be working fine yeah and that's the question and then it gives us the start button again so the quiz is working and that's super sweet so this is how you build a fairly simple little quiz game with react and typescript there are room for improvement but hopefully this gave you some insight in how it is to build an application with typescript and react so if you like this kind of tutorials make sure to subscribe and support me I will put out these tutorials regularly on my channel and hopefully I see you in another one
Info
Channel: freeCodeCamp.org
Views: 196,309
Rating: undefined out of 5
Keywords: quizapp
Id: F2JCjVSZlG0
Channel Id: undefined
Length: 80min 1sec (4801 seconds)
Published: Thu Jul 09 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.