Build a Memory Game in React Tutorial
Key Takeaways
This video tutorial demonstrates how to build a memory game in React, covering topics such as fetching data, managing state, and implementing accessibility best practices. The tutorial provides a step-by-step guide on building a polished project, including designing reusable components, implementing user interactions, and handling errors.
Full Transcript
learn to build an engaging and accessible memory game while mastering essential react Concepts from State Management to API data handling through Hands-On development you'll create reusable components Implement game logic and learn important accessibility practices that make your applications inclusive for all users IO from scrimba developed this course hello and welcome to this course where we are going to build a memory game the course here is the end product of my time in the scrimba teacher talent program and I am very excited to share it with you all to build our memory game we'll use the react framework and the Emoji Hub API and along the way we will also do quite a bit of work to ensure that the game is fully accessible to any user let's take a look together at what is will be building when the user opens our game what they'll first see is this form where they are to select a category and a number of memory cards when they've done that they click the start game button and get to the actual game here we have all the memory cards lying face down and now of course the users or should we say players job is to find all the matching pairs that are hiding on the other side of these cards so they start clicking and looking for matches and they go on until all cards are matched in pairs when they turn the very last card and thereby match the very last pair a box pops up above the memory cards telling the user that all cards are matched and at the same time giving them the opportunity to Play Again by clicking the play again button as you can see the motivs on the memory cards are emojis and this is of course where the Emoji Hub API comes into play the screenshot you see here is from the API documentation on GitHub and you can click it to go straight to this documentation the API offers different options for fetching one or several emojis and for specifying things like Emoji category so the category that we initially ask the user to select in the form is a category of emojis in this API in this course we will be studying the following things react props how do we pass receive and work with props react hooks how do we work with some of the most common react hooks you'll get to practice working with us State use effect and use ref we will build reusable components This truly is one of the great benefits of working with react we can build components that we can use again and again in various different places in our code we will build a form and practice how to handle and manage form data in react and finally as I mentioned in the beginning we will look into accessibility building a memory game where we rely 100% on emojis that are to be matched in pairs there are some obvious accessibility issues that we will address along the way before you dive head first into this course there are a few things that you should already be familiar with the react Basics so for instance when I say passing props or the use State hook this should not be the very first time that you hear that essential JavaScript Concepts this is not a JavaScript course but we will write quite a lot of JavaScript code I am going to provide you with hints here and there in the challenges but I am not going to really teach you any of these essential JavaScript concept steps therefore it is a very good idea if you're already familiar with those you should also be familiar with how to work with apis I will assume that you know about promises fetch requests asynchronous JavaScript and things like that which are necessary tools when integrating apis into your front end projects though I also want to emphasize that when I say familiar with I mean familiar with you're not supposed to be an expert cuz if you were you wouldn't need to take this course at all if you know about the concepts that I have listed here but feel like you do need more practice solving small stepbystep coding challenges you're definitely in the right place your teacher in this course is me IO with the incredibly Danish last name Bal a name that is unfortunately for me pretty much impossible to pronounce if you are not Danish from the very beginning I I am a scrimba frontend career path graduate and former scrimba boot camp Cod reviewer and since August 2024 I've been working as an IT engineer in a Pharma engineering company if you want to get in touch feel free to reach out to me on the scrimber Discord server or on LinkedIn you can click the links here to get to my profile on each of these platforms before we get going with the course there is one last thing that I want you to know about me I am an autistic trans person I'm sharing this with you because I want you to know that I use the gender neutral pronouns they them and also because you can think of me as an example of something which I really love about the world of coding there is room for everyone here it doesn't really matter who you are or what your story is as long as you can code you're in okay that was enough of me talking I think are you ready to write some code well I take that as a yes see you in the next scrim in order to ensure that you get a head start in this course I have written some boilerplate code for our memory game in a minute I'll walk you through this code and show you how our app is working at this stage but before I do that I would like you to take a good look at everything on your own more specifically I want you to take a good look at the react code that we have here inside of the app component and I also want you to look at the three component we have out here in the SAR in the components folder while you're doing that it would be great if you write some code comments think of these comments as notes you write to yourself to ensure that you really understand what is going on in the code right now I would also like you to run the code to see how our app plays out in the mini browser so please pause the scrim now take a tour inside the app and I'll be back with you in just a second to walk you through everything we have okay I hope you took the opportunity to familiarize yourself with the boilerplate code the first thing I'll do now is to run the code and show you our app this is our start screen and all we have here as you can see is a heading memory and then we have this start game button the button lives inside of the form component and when we click it we get 10 emojis or five emoji pairs rendered to the screen one obvious thing that you probably thought of yourself as well is that right now our memory cards are giving away their value as soon as we start the game as we saw in the previous scen where I walked you through the functionality of the entire game our goal is to display memory cards lying face down with a question mark on them so that we don't give away anything about the value they have but for now this is what we get when we start a memory game if we click one of these cards we get memory card clicked locked to the console and this goes for each and every card no matter which one we click we get the same message locked to the console if we look at the return statement here in our app component we see that this is where we control the conditional rendering of the form and the memory card components we also have a piece of State up here the is game on bullion that is initialized to false and then the setup function set is game on and then we have these two functions the start game function and the turn C function the first one of these start game is passed through props to the form component here inside the form we receive this prop and pass it further on to the regular button and finally the regular button component returns a button where we use a children prop as the content of the button and we pass the handle cck prop to the onclick event handler the way we start a game right now is simply by flipping the Boolean value of is game on to true and we do that right here inside of the start game function furthermore we use the event that we are receiving as a parameter to prevent the default behavior of hitting a button inside a fa form element when the S game on bullion is flipped to true we render this memory card component it returns an unordered list and the list items are created up here by mapping over the Emoji array the Emoji array is the one that we have up here it is a hard cuted array of five different Emojis all occurring twice here we map over the array and for each iteration we grab the Emoji itself and its index and then we use the index as the key on a list element right here and we use the emoji as the content of the button down here finally we receive the prop handle click and pass it to the unclick event handler here the value of the handle click prop is as you can see down here the tone card function and the only thing this function is doing right now is to console lock the string memory card clicked so to summarize this this spoiler plate code gives us an idea of what we are aiming for we want to be able to start a game and turn some cards but we are far from actually having a functional memory game so in the rest of this course our job will be to transform this rather poor imitation of a memory game to an actual game where we can turn and match memory cards besides all of the react code that we've looked at now there are a few more files out here in our sitebar inside of this data folder we have a data.js file it contains an object with two key value pairs category and number and this is the data that we'll use to create reusable form elements we also have this index. HTML file honestly there's not much to say about this one it's just a very basic setup with an app title and the import of Google fonts and so on and then finally we have an index. CSS file to allow you to focus only on react I have written all the CSS in advance that means that your only job when it comes to styling is to use the class names that I tell you to use when you do the challenges I hope that you really took the opportunity to familiarize yourself with this spoiler plate code cuz now it's time to move on to the next grim and start writing some code see you there as we saw in the previous scrim the boiler plate code that we have right now isn't much of a memory game actually because if we run the code all we can do is click the start game button we get some hardcoded emojis and when we click them we just get this console lock memory card clicked so in this scrim we're going to take the first step in order to get some data from an emoji API instead of using our hardcoded array of emojis that also means that it is time for your first challenge give me a second while I paste in the challenge here there are three parts to this challenge first you should turn the start game function into an async function so that we are ready to work with promises Second Use the TR catch syntax and make a fetch request to the Emoji API with the URL I'm giving you here and store the response that you get back in a con called response lastly check if the respon answer is okay and act accordingly I have described here what act accordingly means so please read through the challenge text carefully to make sure that you understand all the steps you need to take I have a hint and a warning for you as well the hint is remember the await keyword and the warning is you won't be able to see any of the emojis that you are fetching from the API at this stage we are merely fetching and console looking if any of this seems overwhelming to you at this stage remember that Google is your friend you will be able to find help when it comes to the asyn weight syntax or the try catch syntax if you feel unsure of how to use that so what are we waiting for roll up your sleeves give this your very best shot and I will be back with you in just a second to show you my solution okay I hope that went well and if not don't panic we will fix this together first we want to turn the start game function into an async function it is as simple as this we just write the async keyword in front of the function and we are done second we need a try catch block and we need to do something inside of these blocks so let's get started with the basic syntax here we have our Tri block and our catch block and we are ready to put some code in here now what we want to try is to make a fetch request to this URL so we say fetch paste in the URL we store this in a c score response and because we're working asynchronously we need to await whatever is coming back from the fetch request now that we have a response we need to check if it is okay or not meaning we have to check did everything go well did we get back something that we can work with or not and we're going to do that inside of an if statement so we check if the response is not okay and inside of here we are going to do some error handling and if it is okay we can move on On To The Next Step which is to get the data from the response store it in a const and log it to the console and then finally call the set is game on function with the Boolean value of true so we say const data then we await the response and we need to use the Json method on this one now we can conso log the data and we can call this function that we have down here so we got the happy path of and running if everything goes as we wanted to this code will be executed if we run into trouble on the other hand we'll need to do something in here and what we'll do is we'll throw an error and in the parenthesis here we will add a custom error message could not fetch data from API down in the catch block we want to console lck this error method and we do it by receiving it here and then we say console error and passing the error so this should be it for this challenge let me just remove all of the text here to buy us some space open up the console and let's try to run the code now we hit start game and oh no we got a reference error I misspelled something somewhere let's take a look yeah this is it response okay let's drag in now it's working the data we get back as you can see is an array and it is a lot of data and here it's an array of objects and these objects each have five key value pairs name category group HTML code and unit code so our fetch requests seem to be working we've got the happy path up been running now let's check that our error handling is actually working I'm just going to manually sabotage this URL and then run the code again start the game and our catch block is successfully catching the error so we get our custom error message locked to the console down here so now that we got some data back from the API we are ready to move on and in the next scrim we are going to store this data in state so that we can work with it appropriately in react in the previous Grim we successfully made a fat request to the Moi Hub API and we store the data that we get back from this request right here in this variable that we simply called Data in this scrim it will be your job to take a sample from this data and save it in state to make it available to us throughout the entire app so I hope that you're ready cuz it is challenge time for you now in set one I want you to create a new state variable called emojis data with a corresponding set of function and initialize it as an empty array in step two go into the tri block of the start game function and create a new variable called Data sample this data sample should be equal to the first five elements from our data here in step three store the data sample as emojis data in state and finally in step four I want you to log emojis data to the console I would like to give you a hint and a warning as well in step two you can use the javascript. slice method to get the data sample and the warning here we are still rendering our hardcoded emojis so all of the hard work that you're doing right now is not yet visible in the mini browser now pause the scrim do your best to solve this Challenge and I'll be back with you in just a second to show you my solution okay I hope that went well let's do this together we'll start by creating our new state variable up here at the top of the component we do that using the cons keyword then we open up our square brackets type out the name of our state varable emojis data and after the comma we create the new Setter function set emojis data then we set this equal to use state with an empty array as the initial value that was it for step one in step two we want to get a data sample from this data variable we have here inside of Tri block we'll start by creating the data sample variable itself using the cons keyword again and now we set this equal to data do slice and inside of the brackets here on our slice method we specify which element we want from data and those are the elements between index zero and index 5 index 5 will not be included here so what we'll get is index 0 1 2 3 and four that was step two done in step three we want to store this new data sample as emojis data in state so here at the bottom of our Tri block where we are also setting is game on to True we'll use our newly created set of function set emojis data and then inside the brackets set data sample to be the new value of emojis data that was it for step three finally we should console lock emojis data we do that up here right below our state variables and that should be it for this challenge let's run the code and see how we're doing here as soon as our app component renders for the very first time we get an empty array lock to the console which is as you know the initial value of emojis data now let's click on start game button to fetch some new data from the Emoji Hub API and look at that we still render hardcoded emojis in the mini browser of course but down in the console we now have an array containing five objects we are successfully fetching the data getting a sample and storing it as emojis data in state excellent in the next Grim we'll start looking into how we can render this data on our memory cards so when you feel ready for that I'll see you in the next scrim in the previous scrim I promised you that we were now ready to render the API data the emojis that we get from calling the API to the mini browser but I have to admit that that was not quite true I misled you a bit on this one because before we can do that we have to talk about HTML entities as you may or may not already know HTML entities are special codes that we use in the HTML to represent reserved characters or characters that are not easily typed on a keyboard for instance the code you see here starting with an ENT and a hashtag and ending with a semicolon is translated into that cute little monkey face another example of something that you might see more commonly used is the HTML entity representing a copyright symbol now the reason why we have to talk about this now has to do with what I'm about to show you next h HTML entities behave differently depending on how we use them in our code if we had code an entity directly into the HTML or the jsx in a react app we don't have to do anything The Entity is automatically decoded meaning it is translated automatically into whatever we are trying to display but on the other hand if we take this entity and store it in a variable it will not not be decoded automatically meaning that we have to do something to decode it let's take a look at some code to illustrate the issue here in this very simple react app I have an H1 and a button it looks like this in the mini browser this cute little monkey face is created using the same code as the one I showed you on this slide previously so the HTML entity here translate into the monkey face now if we take this HTML entity and store it in a variable you will be able to see the issue here in action so I have created a cced monkey face entity with the same value as the one I have on my button and now I'm going to display this monkey face entity on a button next to the other one and when I run this code this is what we get we have the monkey face display correctly here and then we have the actual HTML entity displayed here instead of the translation into monkey face and this is simply because when we store the HTML entity in a variable we have to decode it luckily we have libraries that can help us do that the screenshot you're seeing here is from a library called HTML entities and the screen shot is at the same time a link to this documentation and I recommend that you pause the scrim and go there and read through the documentation at your own pace in short we are going to use this library to decode the variable when we render it on the button so the process is this you won't be able to see everything I do now so I'll walk you through it when I hover over this sideb here the three dots are showing up for me I click those then I say add dependency in the drop-down menu and in here I type the name of the npn package I want to install and now you see out here in the sidebar I now have my HTML entities installed the next step is to import decode entity from this Library so I say import and it's a named import so I need my curly braces and the import is from the HTML entities now I can use the decode entity method on my monkey face entity when I am rendering it so I say decode entity and I pass the variable into the brackets if I run the code again now I should get two monkey faces side by side and I did so the lesson here is when you work with HTML entities you need to distinguish between entities hardcoded in your HTML or jsx and entities that you somehow store in a variable and with our knowledge of HML entities now up to date we can move on to the next scrim now we are finally ready no more sides no more details it is time to render our emojis data to the mini browser so without further Ado I will paste in a challenge for you this challenge comes in two parts part one is that I want you to pass the Emojis data that we have saved in state as a prop called Data to the memory card component and just to remind you the memory card component is this one that we are rendering down here part two of The Challenge is written out inside of the memory card component here I want you to receive the data as a prop and I want you to to use this data to render the emojis that we fetched from the API remember that the data is an array of emoji objects so what you could start out by doing is logging the data to the console to see what property on this object that you should be rendering as the content of the button I do of course have a hint for you as well you know how to decode HTML entities and if you look closely at the sidebar to the left you will see that I've been so kind as to already install the necessary dependency for you so what are we waiting for please pause the scrim jump into the code and get those emojis rendered to the mini browser I'll see you back here in just a second and show you my solution the first part of this challenge should not cause too much of a headache we want to take the Emojis data and pass it as a data C to the memory card component so we go down here and say data and we simply pass the Emojis data and that is it for part one of the challenge inside of this memory card component we start out by receiving this prop so I add it up here and let's console lock it to remind ourselves what it is we are receiving so we run the code we start the game open up the console and let's inspect this for for a while since you know everything there is to know about HTML entities you hopefully figured out that what we need here is the HTML code which comes in the form of an array all of these simply have one item in that array other parts of the data from the API has two items in the array both of which are HTML codes so we will settle with just always scrapping the first item in the HTML code ARR so the next step here is to swap this Emoji array for the data that we are receiving we still want the Emoji as well as the index and we can leave everything as it is except for this part the Emoji here represents each object in the data array so on each Emoji we want the HTML code and since it's an array and we want the first item in that array we will add square brackets and zero now if we render this as it is we will get the actual HTML code instead of the Emoji represented by this code so we also need to decode this entity so up here at the top of our file we'll import the decode entity from the HTML entities's library with that in place we can now use the decode entity method down here so we wrap this in Brackets and say decode entity let's just close the console now hopefully everything is working now we've done all we need to do so we can delete the challenge text we can delete the console log we can delete the hardcoded Emoji array and run the code so we start the game and we get the Emoji is that we fetched from the Emoji Hub API if you manage to figure out all of this on your own give yourself a pad on the back that is an amazing job you just done there take a minute to celebrate or get some fresh air if you need to and I'll see you in the next scrim now that we are finally rendering memory cards with the emojis that we fetched from the API you probably realized there is one obvious issue here we are rendering five unique emojis not 10 memory cards with five emoji pairs on them and frankly that is pretty useless in a memory game where the whole point is to find and match pairs to fix this issue we'll have to write quite a lot of JavaScript code in our app component and we will break this down into multiple steps and multiple scrims but before we start writing any new code let's talk about in plain English what exactly it is we need to do here first of all a memory game requires matching pairs so we need to duplicate each unique Emoji second just like you would shuffle a deck of cards before playing a card game we have to shuffle our emojis data in order to display the memory cards in a random order it would simply be too easy and thereby also rather boring to play the game if the matching cards were always in the exact same positions both of these things are essential without shuffled pars there simply is no memory game though I would like to add a third task to our to-do list here and that is to randomly select five emojis from our API data so that we don't always display the same five emojis on our memory cards this is not something that we strictly have to do but I think it's a nice touch to create variation in the game now that we have loads of emojis available to us in the API the next question that we have to ask ourselves now is in what order should we do all of this well logically we have to start out by getting random emojis from the API data so let's move this one up we place get random emojis from API at the top of our to-do list and call it step one after getting these five random emojis we then want to duplicate each of them so we can leave this step here duplicate unique emojis and call it step two the third and final step will obviously be to shuffle the Emojis data okay so this is what we have to do step one get random emojis from API step two duplicate unique emojis and step three Shuffle emojis data in the next SC we'll start working on step one so whenever you're ready I'll see you there as we established in the previous Grim the first thing we have to do when we want to go from rendering five memory cards with five unique emojis on them to instead render 10 cards with five randomly selected Emoji pairs is to actually get these five random emojis from our API data up until now we have worked with this data sample here which is an array of the five first emojis that we get back from the API we use the do slice method and thereby the indices of the Emoji objects in the data array to get this data sample the question that we have to ask ourselves now is how can we get emojis at random indices in the data array instead of always getting the first five and actually I want to give you a second to try to come up with a strategy of your own before I tell you how I intend to solve this one so I have created a minute challenge for you here it is I want you to try to come up with an answer to the question I just asked you how can we get emojis at random indices in the data array instead of always getting the first five pause the scrim now give this some thought and return to me to hear my answer to this question okay how did that one go do you have any ideas for how to do this no matter what I'll share my strategy with you now we are going to generate five random numbers and then use these numbers as indices to get random emojis from the data array so far so good but um how do we know if the random numbers that we generate can actually be used as indices I mean what if we generate numbers that are too large to work as indices in our data array just to give you an example if we had an array of say 10 items and then randomly generated the number 47 we wouldn't be able to use that as an index I want you to think about this one as well so here is another mini challenge try to answer this question here how can we get random numbers within a range that allows us to use them as indices in the data array pass this scrim give this some thought and I'll be back with you in just a second to give you my answer any ideas here is my strategy we have to ensure that the range of these five random numbers is the exact same as the length of the data array okay I hope that these initial problem solving exercises got you warmed up cuz now it's time for you to get your hands on the keyboard again in step one of this challenge I want you to create a new function called get random indices right here below the start game function it should receive data as a parameter and we'll get back to in a second what data is in this context in this new function you should declare a new variable called random indices array and initialize it as an empty array after you've declared this variable meaning right below it you should use a for Loop to generate five random numbers within a range equivalent to the length of the data array and push these numbers to random indices array and then finally return random indices array at the bottom of the function finally I want you to go into the tri block of the stock game function and lock the return value from get random indices to the console passing data to it as an argument so just to be completely clear when you call the get random indices function inside the tri block the data you're passing is this one here it's the data that we get back from the fetch request to the API and therefore obviously the data parameter that the function should receive as I described in Step One is the same data I want to give you a hint as well we want exactly five unique random numbers so what can you do inside the for Loop to ensure that we'll actually get that pause the scram now do your very best to solve this challenge use Google and chat gbt if you need to and return to me to see my solution okay I hope that went well let's do this together we'll start by creating our new function here and we know that this function should receive a parameter called data that was that one inside the function the first thing we want to do is to declare a new variable called random indices array we'll do that using the const keyword and we'll initialize this variable as an empty array that was step two now to the for Loop which was probably the trickiest part of this challenge we'll start by saying four then open up the brackets and then let I equal Z this means that on the first iteration through this loop I is equal to zero now we want to specify how many times we want the loop to run we want five random numbers so we want the loop to run five times and therefore we say I is less than five and finally we increment I by one for each iteration so we say i++ inside the loop we want to Generate random numbers we can do this by declaring a new variable I'm going to call this one random num and set this equ Al to a random number within the range of the length of the data array to do that we'll use javascripts math.random method this method generates random decimal numbers between 0 and one we know that decimals are of no use to us as indices so we'll start by flooring this so we wrap this in Brackets and then before the brackets we say math. floor this would give us a random number which is always zero because a floored number between Z and one will always be rounded down to zero so now in order to get random numbers in a Range that is equivalent to the length of the data array we're going to say math random multiplied by data. length now we've got our five random numbers and we want to push those to the random indices array though we want to make sure that each of these numbers are are unique so we need to check that the number that we are currently pushing is not already in that array to do this we create an if statement and the condition that we want to check for is if random indices array includes random num or not so we can use the exclamation mark then say random indices array do includes and in the brackets here on the includes method we say random num so only if the random IND array does not include the random number will push random num to random indices array but what happens then if just by chance we generate the same random number twice let's say we generate the number 20 two times then the second time this for Loop generates the number 20 nothing will be pushed to the array and we'll just move on to the next iteration so our random indices array will end up containing four unique random numbers not five because one of our iterations just led to nothing so to ensure that we don't end up in a situation where our five iterations generate less than five unique random numbers we need an lse statement here as well and what we'll do here is that we'll subtract one from I this way we can be absolutely sure that if the random number that we generate up here is not pushed inside the if block to the random indices array because the same number is already in that array then we'll create an extra iteration in our for Loop by subtracting one from I because it's the value I up here that determines how many times this Loop will run so that was it for the full loop now we simply have to return random indices array from this function and this was step three done the last thing we have to do now is to go up here inside the tri block and console lock whatever is returned from get random indices so we write a console lock and inside of this one we call the function passing it data as an argument this should be it so let's delete the last part of the challenge now we open up the console run the code and start the game to invoke the start game function and thereby invoke our new get random indes function and down in the console we get an array of five random numbers right now they are in the range between 5 and 77 let's just do the same thing again to see what other numbers we can get here this time we got values between 14 and 97 let's go just one more time now we are in a range between 17 and 100 so we clearly have a lot of data here at least 100 different emojis okay great now we have some random indices to work with and in the Next Room we'll use use these random indices to actually get five random Emoji objects from the API data when you're ready to tackle that I'll see you there in this scrim we are going to use our newly created get random indices function to get a data slice of five randomly selected and unique emojis from the API data and will also display these emojis on the memory cards in the mini browser so if we look at our to-do list again you can see that we are still dealing only with step one here to complete the task at hand we need to create another brand new function and we also need to write some more code in the start game function there are quite a few steps to this though I believe that you can do it so let's just get going with your next coding challenge first below the start game function I want you to create a new function called get dat slice the function should receive data as a parameter and this data is the exact same as the one we would dealing with in the previous scrim the data variable up here that we get from calling the Json method on our response inside this new function make a call to get random indices and store the return value in a new variable called random indices in step three map over random indices and use the random numbers stored in this array to create a new array of random emojis selected from data store this new array in a variable called Data slice and return it at the bottom of the function inside the tri block of the start game function make a call to get data slice passing data as an argument and save the return value in a variable called Data slice then delete the data sample variable and replace data sample with the new data slice variable in the set emojis data function finally when you've done all of this run the code and start a new game to check that your code is working and how do you know if it's working well you should see that in our mini browser where we currently have the five first emojis that we fetch from the API you should instead see five memory cards with five randomly selected emojis now do your best to solve this Challenge and I'll be back with you in just a second to show you my solution so how did that one go I hope you managed to solve the challenge and if not don't panic we'll go through everything together now first of all we need to create a new function I'm going to do that right here below the start game function and the challenge text our function should be called get data slice and it should receive data as a parameter that was step one in step two we want to make a call to get random indices as you know from the previous scrim get random indices receives data as a parameter so we of course have to pass data as an argument when we make the function call and then we store the return value from this function call in a new variable that we call random indices now we're done with step two on to step three here our job is to create a brand new array of Random emojis selected from data and we do that by mapping over random indices so we say random indices do map now we have to decide what we want to call the items that we are mapping over in this array I am going to call these items index because we're going to use each and every one of these random numbers as indices then we create the arrow function here and what we have left to do is to use index on the data array so we say data square brackets Index this operation here gives us a new array that we want to store in a variable called Data slice finally we want to also return this new data slice variable from our function if we wanted to we could actually write our code in a slightly different way here inside of our G data slice function let me show you instead of saving the new array in a variable called Data slice and then return data slice we can actually just return the entire expression here this is very concise code it looks really professional but in my opinion it is a bit less readable than what we were doing before where we named this new array data slice and return that data slice variable I think it's easier to see what's going on here which is why I personally prefer this solution now on to step four inside the tri block we want to make a call to get data slice passing it data as an AR the return value from this function call is the data slice array that we just created so now we're going to store it in a variable that we again call data slice that was step four now in step five we have a bit of cleaning up to do we no longer need the data sample variable so we can delete that one and since data sample here no longer exists we want to replace that with data slice the only only thing we have left to do now is to run the code cross our fingers and hope that everything is working so I'll delete this last bit of the challenge run the code and start the game and look at that these emojis are BR new to us and that's because we just successfully fetched random emojis from the Emoji Hub API our next task is to tackle step two and three on our to-do list that is to duplicate and Shuffle these emojis so that we actually get 10 cards with five emoji pairs on them render it to the mini browser and this is exactly what we'll be doing in the Next Room when you're ready to move on I'll see you there in the last two scrims we worked on step one in our to-do list and built the logic for selecting random emojis from the Emojis data that we fetch from the Emoji Hub API now it is finally time to complete step two and three so in this scrim we're going to write a function that duplicates and shuffles our randomly selected emojis once again I'll do a bit of work for you and make some changes here in the app component before I give you a challenge okay let's take a look at these changes together down here below the get random indices function I have created a new function called get emojis array this function receives a parameter called Data the call to this function is made up here inside of our start game function when we call get emojis array we pass it data slice as an argument as you know data slice is an array with five randomly selected emojis from the Emoji Hub API then we store the return value from get emojis array in this variable called emojis array and finally in this setup function down here we set our emojis data to be this new emojis array just as in the previous scrim this code is currently broken because there is no return value here in our get emojis array function and therefore we cannot obviously store a return value in a variable so it will be your job now to write the code that we need inside the get emojis array function to get our code up and running here is what I want you to do in step one you should create a new variable called paired emojis array this variable should be an array that includes each object from the data array twice and remember data is an array that we're receiving as a parameter and it is equal to the data slice and when I say that each object should be included twice that is of course because this is where you're going to duplicate each unique Emoji in step two I want you to use the Fisher yades algorithm to shuffle perod emojis array and finally return this array at the bottom of the function in step three you should simply run the code and start a new game to check that your code is working I do have a couple of hints for you as well in set one you can use the array spread operator to create a new array and in step two you should Google the fish Yates algorithm you're not supposed to know this algorithm by heart you're not supposed to be able to just type it out from memory I can't do that that either you'll see that later when I walk you through my solution so Google it all right Pastor scrim do your best to solve this Challenge and return to me to see my solution so I hope that went well let's get to it we'll start by creating the new variable paed emojis array using the const keyword what we want to assign to this variable is a new array and inside of this array we want every object from data but we want to duplicate them and we want objects we don't want any nested arrays in here and that is why we're going to use the array spread operator so we spread in the data and this gives us basically just a copy of the data array because we're spreading in everything inside data into this new array that we call paired emojis array so now that we want every object to appear twice in the array what we do is simply that we spread these objects in twice so we add a comma here and then do the exact same thing again we spread in the data that was step one in step two we are to use this Fisher Yates algorithm and I'm now going to do something that you'll never see me doing again in this course I'm going to copy paste a lot of complicated code and not go through it in detail just give me a second here it is the f fure Yates algorithm that shuffles items in an array so that we get them in a randomized order you really don't have to understand exactly what's going on inside of this for Loop because that is Way Beyond the scope of this course all you have to know is that you can use the fates algorithm to shuffle array on the other side of this for Loop when we have run perod emojis array through it we have an array with duplicated emojis in a randomized order so all we need to do now is to return this array and that was step two finally we are to run the code to see how this went I'll delete the challenge text run the code and now to the Moment of Truth we start a new game and hopefully we see 10 memory cards five emoji Pairs and a shuffled order look at that we made it I don't know about you but I am really happy about this now this memory game is going to be awesome I imagine that solving step one two and three on our to-do list was hard work so please remember to take a break to not wear yourself down completely and when you're feeling refreshed I'll see you in the next scrim before we push forward building out the logic of our memory game I need to take a moment to address a few discrepancies in our code that will feel themselves in the next scrim you see the three scrims that you just watched were re-recorded after I finished recording everything else and the reason for this is that I discovered two issues in the code that I wanted to fix though unfortunately for me recordings show no mercy as you know so what you'll see in the rest of the course is the code as it looked before I discovered the issues let's take a look at these two issues one at a time inside our start game function I have now added the weight keyword before two of our function calls here and I have also made the functions themselves asynchronous so down here we have the async keyword in front of the get data slice function and the same down here the async keyword before get emojis array this is what you'll see in the rest of the course though the thing is it's not actually necessary for these functions to be async the code here works perfectly fine it does not break anything to use the asyn syntax on functions that can run synchronously the only issue with this is that it adds an unnecessary layer of complexity to the code and makes it a bit harder to read and understand to give you a chance now to learn from my mistakes let me explain why these two fun functions don't need to be async the start game function itself must be async because we are indeed performing asynchronous operations inside the function body we have to await the fetch request here on line 13 before we proceed to check the response in line 15 we also have to await the JM method that we call on the response down here on line 19 before we can store the API data in the data variable though now that we have the data safely stored in a variable we no longer need to await anything the rest of our code here can run synchronously so there's just no need for awaiting these functions to do their thing the second issue I discovered is again not about broken code but rather about unnecessarily complex code as you probably remember here in the get data slice function we use the map method on random indices to create a new array of randomly selected emojis though as you can see here that super neat solution that allowed us to write everything in one single line has now been replaced with four lines of more complex code here I use the do reduce method to sort of manually achieve what the do map method gives us right out of the box it works as intended nothing is broken but it is kind of like Reinventing the wheel it's not incorrect it's just unnecessarily complex moving forward in the course the code will look as it does here in this scrim so just remember if you at some point need a reminder of what is going on at this part of our code base and how everything works then go back and rewatch this and the three previous scrims okay with this out of the way we can move on to our next big task which is to build the logic for turning or selecting memory cards when you're ready for that I'll see you in the next scrim up until now we have made a lot of art work related to starting a memory game and rendering our memory cards to the mini browser our next big task is to figure out what should happen when we click a memory card down here at the bottom of the app component we already have a turn C function setup this function is passed as the value of the handle click prop to the memory card component right here we obviously want this turn C function to do something else and more than just logging the string memory can't click to the console but before we can start writing any new code there's something we need to consider therefore I have prepared this mini challeng for you I want you to think about what information on a memory card we can use to one identify which card was clicked and two identify matching Emoji pairs you shouldn't have to write any new code to solve this challenge but I highly encourage you to conso out the Emojis data to see what we have to work with please pause the scrim now do what you have to do to come up with answers to these two questions and return to me when you think that you've got it did you figure it out the answer to question number one is the index and the answer to question number two is the name of the Emoji to illustrate why that is we'll take a quick look both at the app itself and at the Emojis data due to the nature of a memory game there are no unique values on the Emoji objects that we render here every unique Emoji is duplicated and appearing twice on the screen so the only way that we can tell this cat from the next cat over here is by looking at their position and the position is as you know the index of the object in the Emojis data array now let's take a closer look at the Emojis data here I have conso locked the Emojis data started a new game and simply copy pasted the very first item from the Emojis data array and pasted it in here we have five properties on this object two of them the category and the group here are of no use to us in this case because they are not unique to each Emoji the three remaining properties the name the HTML code and the Unicode are all unique to each Emoji they're not unique to a memory card but they are unique to an emoji technically we are therefore free to use any of these properties to identify matching Emoji pairs but as a service to our fellow developers we're going to go with this one the name property and this is simply because the string bare face is much easier for a human being to read and understand than for instance this HTML code down here and present # 2859 semicolon now that we've got this settled I believe that you are ready for your next proper coding challenge there are two parts to this challenge first I want you to go into the memory card component in here you should pass the Emoji dotame and the index as arguments to the handle click function down here second I want you to go back into the app component and do some work on the turn cut function here I want you to receive the name and index as parameters and for now simply lock them to the console to check that everything is working as expected please pause the scrim now jump into the code give this your very best chart and I'll be back with you in just a second to show you my solution okay I hope that went well let's start in the memory card component when we pass arguments to a function reference just like our handle click here there are two things we need to do first we add the brackets and we pass in emoji name and index and this is pretty much what we always do when we pass arguments to functions second we need to place this handle click function inside of an arrow function like this the reason why we need to do this is because as soon as we add these brackets after the function name handle click we immediately invoke this function as soon as the memory card component renders so since we want this function to run only when one of the cards is clicked we pass the arrow function as the function reference to the unclick event handler and this Arrow function in turn calls the handle click function back here in the app component we simply receive these parameters in the way that we always do in JavaScript functions so we write name name and Index right here in the brackets and the last thing we have to do is simply to change what is locked to the console I chose to create this template literal here if you did something less fancy and just locked the name and the index to the console as they are that is completely fine that was all that we had to do in this challenge so let's run the code and check that everything works as we expect we start a new game and click our first memory out and down in the console we get the Emoji all at index Z was clicked to check that our code really is bullet proof I think we should click the other a here as well this one and down in the console we get the Emoji L at index one was clicked excellent this means that our turn card function is successfully distinguishing between the two different outs it also means that we are ready to move on to the next scrim see you there in the previous scrim we did some work inside the memory card component and here in the turn card function inside of our app component we passed the index of the click memory card and the name of the Emoji on this card to the function and loged those values to the console our task now is to take this information the name and the index and store them in state so that we can keep track of which cards are clicked meaning selected by the user I am pretty confident that this was enough of an introduction to your next coding challenge so let's just get to it what I want you to do is this first create a new variable in state called selected cards with a matching set function and initialize this variable as an empty array second go into the turn card function and set the value of selected cards to be an array containing one single item this item should be an object with two key value pairs where the values are the function parameters and third log selected cards to the console to check that your code is working as expected please pause the scream now give this challenge your very best shot and I'll be back with you in just a second to show you my solution okay I hope that went well let's start out by by creating some new values instead we'll go up here right below the Emojis data and say const then we open up the square brackets and say selected cards and then we add the setter function set selected cards and we initialize this as an empty array and that was part one of the challenge done now let's scroll down to the turn C function I'll start out by deleting this console lock since we won't need it anymore then we use the Seto function that we just created in state set selected cards we open up the brackets and what we want to set these selected cards to be is an array so we use the square brackets inside of this array we want an object so now we use the colly brackets and inside of this object we want two key value pairs there are two ways to write this object the first one is this we select a name for our first key and I'll just call it name and then we set the value of this key to be name and then we do the same with the index we call our key index and give it the value of index now as you can see we are repeating ourselves here because our keys and our values in both of these pairs are identical as you might already know we can use an object shorthand to avoid this repetition and all we have to do is to delete the key so we delete this name key and just leave the value name and we of course do the same for our index delete the key and leave the value Index this syntax will give us the exact same object as the one we had before that was part two of our challenge done the only thing we have left now is to console log the selected crots okay we have a console lock in place we can delete the last bit of the challenge text and run the code to check that everything is working as expected we start a new game and click an emoji I'll take this one just because it's cute down in the console we can now see that the value of selected cards is an array containing one single object two key value pairs the key name has the value tiger phase and the key index has the value one so far so good this was in fact the solution to the entire challenge I have for you in this scrim but we are not quite done yet let's find out what will happen if we try to add more cards to the selected cards array if I now click this pig here for instance down in the console we get an array containing an object with a name property with the value of pck and an index property with the value of four this is pretty good because it means that our turn cut function is successfully keeping track of the cards clicked by the user and saving them in state but when we clicked the P we lost our tiger face this happened because of the way we wrote Our code inside the turn card function inside of our set of function we set the value of selected cards to always be the last card that we clicked thereby we are unfortunately also actively deleting any values previously stored in this array this will happen no matter which C we click no matter how how many cards we click we will only be able to store the very last card we clicked in the selected cards array to solve this problem we need to write some more code inside of our turn card function and that is exactly what we'll be doing in the next scrim see you there after all of the hard work we have done we are now very close to having the logic for adding clicked card to the selected cards array functioning in the way that we want to in the previous scrim we identified an issue with our current code namely that selected cards can only ever contain an array with one single object in it before we go ahead and start fixing this problem I want you to try to figure out if there's anything else we need to consider when we write our new code inside the turn card function therefore I have prepared this mini challenge for you based on the rules and mechanics of a memory game I want you to try to define the conditions that we need to build into our turn cart function you should make sure to consider the following aspects one how many times can a card appear in the selected cards array and by a card I mean one in the same card and two what is the maximum number of cards that we can have in the selected cards array at any given time this minute challenge is not about writing code code I don't expect you to write any code whatsoever I don't expect you to define the conditions in code but I highly encourage you to write sudu code to try with your own words in plain English to explain what it is that we have to do here so please pause the scrim now try to figure this out write some pseud code and return back to me when you think that you've got it okay hopefully you came up with some clever answers to these two questions my answers are short and simple any given card can only appear in the selected cards array one time and the maximum number of cards that we can have in the selected card array at any given time is two let's just take a quick look at our app to make it completely clear why this is the case in any memory game whether analog or digital the mechanics are the exact same the player starts the game by turning a card this one here for instance with a b as its value and now their job is to find the matching B somewhere else in the game so the first thing we want to ensure is that the player doesn't cheat and select this B again turning the same card twice isn't possible in an analog memory game but it is possible in a digital memory game if we don't prevent the user from selecting the same card twice with that rule in place we're now forcing the player to select another card let's take this Rose next to the B now we have a b and Rose visible they are obviously not a matching pair so we want the player to select a new card they then take this rabbit face here or whatever animal that is and as soon as they do that we want the B and the rose to be flipped back lying face down so that their values are no longer visible I have prepared a challenge for you where you are to translate these conditions into code give me a second while I paste it in here I want you to first check if the clicked card is already in the selected cards array and I want you to store the result of this check in a variable called selected card entry next I want you to update the code that adds a clicked card to selected cards and you should make sure that the following conditions are met any given card can only be added once within the same round and the length of the selected cards array should never exceed two finally I want you to log selected cards to the console to check that everything is working I do have a hint for you as well you can use the javascript. find method to solve step one of this challenge go ahead and pause this scrim now jump into the code and give this one your very best I'll see you back here in just a second to show you my solution okay hopefully that went well let's get to work I'll start by commenting out the set function we do need it later on but we don't want it to disturb our work here in the beginning now we'll use the do find method to perform this check described in step one so we say selected cards do findind and inside this call back function we want to check if the index of the clicked Emoji matches is an index that is already stored in one of our Emoji objects in selected CS we reference the objects in selected cards with a parameter I'm going to call that emoji then we write our Arrow function and we access the index property of this Emoji object and ask if a triple equals the index that we receive as a parameter finally we store this check in a variable called selected count entry and that was it for step one next we need to Define some conditions and there are two different scenarios that we have to handle the first scenario is where the length of the selected cards array is less than two here we want to keep any value already saved and state and simply add new values into the array the second scenario is where the length of the array is exactly two here we don't want to keep what's already there on the contrary we need to get rid of that and store the clicked memory card as the new and only value in our selected cards array therefore we need an if statement and we need an else if statement in both of these cases we want to check if the selected card entry is truthy or falsy the do find method that we use here will return one of two things an emoji object that matches the criteria we set up here or undefined if no such object is found so what we can do inside of our conditional blocks is this we start with the exclamation mark and then we say selected card entry and thereby we say only if this value is falsy the code should run then we need double ents to add an extra condition and again in both cases we need to check the length of the selected Cay up here in the if block we want to check if the link is less than two and down here in the elsf block we want to check if it is triple equal to two if the length is less than two that means that there's either zero or one objects already stored in state and we want to keep those objects there so when we run our seter function we need access to the previous state the way we get access to this previous state is by using a callback function here inside of the setto function we reference whatever value is already stored in state I'm calling this pre selected cards then we create an arrow function and now we want to use the array spread operator to spread in this previous value and finally we add the L card in the form of an object to this array the syntax is the exact same as the one we have before so we say name and index down here in the else if block we don't don't care what was previously saved in state we simply want to clear out all previous values and actually we already wrote the code that does this the setup function that we have up here does exactly this so all we have to do is bring it back to live and put it inside the else if block and that was it for step two now finally step three is simply to conso loock the selected cards now let's test this out I'll delete this last part the challenge open up the console run the code start the game and click some cards let's just click the first one here down in the console we see that the value of selected cards is an array containing one object with the name snail and the index zero let's try to click the same snail again nothing happens great we're successfully preventing the player from adding the same snail to the selected C Ray twice how about the other identical snail down here at a different index let's click this one and that works in the console we now have an array with two objects both of them with the name snail but with two different indices and now to the moment of truth what happens when we click a third C I'm going to click this tree out here and it works down in the console we now have an array with just one single object the name is the cious 3 and the index 4 this is absolutely amazing because it means that all of our conditional checks here inside the turn car function are working and applying just as we expect them to if you manage to do all of this on your own give yourself a huge pad on the B and take a second to just celebrate your victories when you're ready I'll see you in the next scrim now now that the selection of memory cards is working it is time for us to look into how we can find matching cards for the human brain this task is super simple and straightforward if we start a new game and turn the first card here and see a tulip and then just by chance we turn the third card and see another tulip we immediately know by comparing these two cards that we found a matching pair there is indeed very little risk of cognitive overload when we perform a comparison like this we know when what and how to compare these two cards our task now is to translate this comparison that we do so easily into code let's start out with a minute challenge just to get you thinking about how we can approach this translation I want you to think about this which tool from our react toolbox can we use to check for matches every time there are two selected CS as you've seen before with many challenges I don't want you to write any code this is a thinking and possibly a Googling challenge all I want you to do is to come up with an answer to this question so please pause the scrim now think carefully about this one and return back to me when you think that you've got it okay did you figure it out the tool we need here is the react use effect hook the basic syntax with the use effect hook looks like this we need to start out by importing it up here where we are also importing use State then right here inside our app component right below our state values we say use effect then we open up the brackets and now we create an arrow function and finally we add a dependencies array and we can open up the function here when the dependencies array right here is empty the use effect hook will run only once when the component first loads if we on the other hand add some value inside of this dependencies array we can control when the use effect runs in our case we will pass selected cards to this array when we do that we are now controlling that the code here will run whenever the value of selected cards changes and as you probably remember the value of selected cards will change when ever the user clicks a card to prove that this is in fact working the way I just described let's just create a console log inside this use effect we'll simply lck the string card selected every time the value of selected cards change you probably noticed here that as soon as I ran the code we got this lock to the console and that is because selected cards is initially set to an M array here so the first time this component loads the value of selected cards is updated and we get C selected lock to the console when we start a new game we don't get any console lock because the value didn't change but as soon as we click a memory card we get this card selected logged to the console now that we know what tool to use namely the use effect hook and how to set up the basic syntax of this hook it is time for your next proper coding challenge first of all I want you to create a new state variable called matched cards with a corresponding setto function and and you should initialize this variable as an empty array second if selected cards contain two matching cards I want you to use the use effect hook to add these card objects to matched cards you should make sure to not override the previous state of matched cards I have a hint here as well you can use the array spread operator to solve step two of this Challenge and just to be completely clear I want you to use this use effect hug that we already set up here to write the code in step two I hope that you're ready for this one please pause the scram jump into the code give this your very best shot and I'll be back with you in just a second to walk you through my solution okay hopefully that went well let's start out by creating some new state up here just below the rest of our state variables we'll say const open up this brackets and then we say matched cards and we create the setter function set matched cards and we initialize this as an empty array and that was step one of our challenge done inside the use effect hug here we need an if statement and we'll use it to check for two different conditions first of all we need to make sure that the length of the selected cards array is exactly two so we say selected card length and ask if it triple equals 2 this is simply because there's no point in looking for a matched pair if we have less than two cards in the selected cards array the second condition that we'll add here is the match itself on every object in the selected cards we have two properties we have a name and we have an index and as we've seen earlier the index is unique to each card but the name is unique to each emoji and that means that we can use the name property to check if the two cards are identical so now we say selected cards and we want to look at the first item in this array so we say square brackets and zero now we are inside the object stored in selected cards and we want to look at the name property on this object so we say do name and then we compare this to the name property of the second object in selected Cuts we do this by asking if this triple equals selected cards at index one do name if both of these conditions are true we know that we' found a matching pair and we now want to add this pair to match cards so we use the Seto function and since we do not want to override the previous stage of matched cards we need a callback function I will call our parameter here prieve matched cards and then create the arrow function and now we can use the array spread operator with the three dots here to First spread in the previous state and second spread in the selected cards by using the spread operator both on the previous state and on the selected cards we ensure that everything that ends up in here are objects if we did not use the spread operator on selected cards if we remove these three dots we would be adding selected cards as an array but we want objects inside of match cards so we put the three dots back in and that was step two of this challenge done so I'll delete the text now I realized I didn't tell you to do this but it is always a good idea to console log to check that your code is working so let's just log match cards to the console we run the code start a new game and let's start out by clicking something that we know doesn't match we'll take this goat here and the camel and in the console we still just get an empty array lugged now let's take the panda and then the other Panda down here and you see down in the console we now have match cards logged out and it is an array containing two objects the panda face and the pandace if we add some other matching cards here let's take the cad and the cad down in the console we now see first the two Panda faces and then the two cat faces so our code is working our use effect is successfully checking for matching pairs whenever we have two objects in the selected cards array and adding these two selected cards if they are identical if you manage to write all of this code on your own that is simply amazing we are now ready to move forward so whenever you feel ready I'll see you in the next scrim we are very close now to completing the game logic in fact there is just one last thing that we need to do and that is to determine when a game is over at this stage in the course I feel pretty confident that I don't actually have to say much more before I give you your next challenge so let's just get to work here is what I want you to do first create a new state variable is game over with a corresponding set function and initialize the variable as false second create a new use effect that sets is game over to True when all memory cards have been matched and the game is over make sure to consider the following what value should we use in the dependencies array and what condition can we use to determine whether the game is over the solution to this challenge involves using the same kind of tools that we used in the previous scrim which is why I have deliberately left this sort of open-ended I want you to on your own use your problem solving skills to figure out how to solve this one so pause the scrim Now put on your thinking cap give this your very best jot and then return back to me to see my solution okay I hope that went well I am sure that the first part of this challenge was easy peasy for you now you have declared so many variables in state so let's just get going with that up here we say const open up the square brackets and then we say is game over and create the setup function set is game over and we initialize this to false for the second part of the challenge we need a new use effect we'll create that right here below the first one here's our basic syntax with the use effect hook the Callback function and the dependencies array inside this use effect we want to flip the Boolean value of is game over to true as soon as the game is over the way I decided to solve this one was with an if statement in here we want to check if the length of matched cards is the same as the length of the Emoji's data when these two have have the same length we know that the user has successfully matched every card from The Emoji's data so we say matched cards. length and ask if a triple equals Emoji data. length though we do in fact need to add one more condition here if we look closely up here at our state variables we see that the Emojis data as well as the Matched cards are initialized as empty array and logically that means that when this component first renders the if statement down here will evaluate to true the game will be over as soon as the app component renders to make sure that the game is actually on and that we actually have emojis data rendered as memory cards to the mini browser we need to first check if we have any emojis data at all and we can do this by checking if the Emojis dat dat. length is true now we have ensured that the code inside of this if statement won't run until we have actually fetched emojis data from the API and rendered it as memory cards to the mini browser and all we have to do now is flip the Boolean value of is game over to True lastly we need to add some value to the dependencies array to make sure that this conditional check here is performed every time we match new cards and we can do that by simply adding match cards to the array and that should be it now I realized that I again forgot to prompt you to console lock is game over I apologize for that but we should obviously do that because otherwise we have no way of knowing if our code works the way we want to so now we have a console l in place and we are ready to run our code down in the console we get false because this game over is initialized to false we start a game and we get false again and now our job is to match all of these memory cards so let's just do it one by one we take the panda then we match the pigs the dog here the bat or whatever this is and the cow and finally we got two locked to the console this happened immediately when we match the final Emoji pair here excellent job completing this challenge now that we know when a game is on and when it is over and we know which cards are selected and matched we are now ready to move on to a very exciting part of this course and that is the styling of these memory cats in the next couple of scrims we will be working on the logic needed to get this styling right I'll see you there in the previous scrim we wrapped up the basic game mechanics and as I announced our Focus will now be to style the memory cards I would like to remind you at this stage that I have already written all of the CSS that we need so your job will be to write the JavaScript and react code necessary for this styling to apply in plain English you could say that the purpose of this JavaScript and react code that I want you to WR is to let each memory card know a bit more about itself let's take take a quick look at our memory card component to see how well each of our cards know themselves when we create the emo L variable here we map over the Emojis data that we receive as a prop we access the Emoji and we access the index of this Emoji in the data array and then we use the name and the index down here and pass those back to the turn card function so a memory card clearly knows its own name and index but it doesn't know anything else back here in the app component we do a lot of work to keep track of the selection and matching of cards we have some State up here we have these use effects both of them here and we of course have the turn cut function down here all of this code contributes to this keeping track of the status of each memory card but since this information about the Sol CED cards and the Matched cards are not passed to the cards themselves they don't know their own status it probably doesn't come as a surprise to you that it will be your job to change that we do have quite a lot of work to do here so we will be breaking it up into multiple steps and multiple scrims the first step will be to set the stage for everything else we have to do by creating a brand new component the component that will create has everything to do with this memory card component so give me a second while I paste in a challenge here for you here is what I want you to do first you should create a new component called emoji button and this component should live out here inside of the components folder the emoji button component should return an HTML button element equivalent to the button in the memory card component and that is this one here second I want you to react our memory card component here to render this new emoji button instead of the current HTML button element you should pass three props to the emoji button and that is content style and handle click the content prop should have the Emoji itself as its value meaning this code here the style prop should have the class names as its value this code here and finally the handle click prop should have the function reference as its f value this code here third I want you to rename the Emoji L variable to card L and the reason why I want you to do this is that I want it to be completely clear that what we are creating in here in the memory card component is a card element while the Emoji itself is rendered in the emoji button component finally I want you to go inside the app component lock selected counts to the run the code and click some cards to check that your refactored code is working so go ahead and pause the scrim now do your best to solve this Challenge and return back to me to see my solution okay hopefully that went well let's get to work we'll start out by creating this new component so out here in the sitebar I click on the components folder then I say new file and I get this popup where I can name my component and as you can see we now have this Emoji button. jsx file open now we write the basic component syntax since we know that we want to export this component we start by saying export default and then we create the function and we call the function emoji button and now we can open up our function body in here we know that we want to return an HTML button element so we say return and create this element so far so good we are not quite done yet as you can see but let's just go back to take a closer look at the button we had inside the memory card on this button we have a class name and we have this unclick so let's get those in place in our new component first the class name and then the unlick in order to to finish up our emoji button component we actually need to move on to step two now to take a look at the props we should pass to this new component we know that we want to replace this button here with the new emoji button component let's start out by importing our new component into this file so that we can use it instead of our HTML button element up here we use the import keyword and since it's a default import we don't need any brackets here with simp simply say emoji buttton and now we import this button from the emoji button file to access this file we need to go one level up back to our component folder so we say dot and then we use the slash to enter the file and finally emoi button now we can use this button down here inside of our component we can start out by deleting the closing button tag here and then we say emoji button here and we turn this into a closing tag with the slash our job was now to pass content as a prop and as you know the content was this part of the code so let's move it up here as part of the props and then we say content equals and then this code as the value the next prop we should pass is a style prop so we simply have to change this class name to style and finally instead of having this unclick here we should pass a prop called handle click now we can go back into our emoji button component and receive these props I am going to directly destructure our props object up here so I open up the curly braces and say content style and handle click inside of the component we can now use the props the class name should have the value from the props style the onl should have the function reference that we pass as the prop handle click and finally the content of this button should be well the content prop and now we are ready to delete Step 1 and two up here and look at step three and four step three was to rename the Emoji L to card L we have an emoji L here and we are also using it down here as the content rendered inside of the unordered list so we'll change those to card L like that and finally we need to log selected cards to the console to check that our code is actually working inside the app component here at the top right below our state variables we'll say console log selected cards all right this was a huge challenge Let's cross our fingers and hope that everything is working now so far so good nothing is broken yet we can start a new game and we get our memory cards rendered in the exact same way as before and now for the Moment of Truth does our turn C function still work it seems to be working down in the console we see an array containing an object with the name tiger and the index of zero if you manag to complete this Challenge on your own give yourself a huge pad on the back this was a super important first step and in the next scrim we'll keep working on the stying of our memory cards see you there in the previous scrim we created this brand new emoji button component and rendered it right here inside the LI element on our memory card our next task is to identify selected or matched cards here inside of the memory card component so that we can eventually add the correct conditional styling to our memory cards in order to perform these identification checks we have some work to do here in the memory card component as well as in the app component I believe that you are more than ready for your next challenge so let's jump into the app component and take a look at what it is I want you to do the first part of this challenge is to pass selected cards and match cards as props to memory card and remember the selected cards and match cards are the values that we have stored up here instead and the memory card component is the one right here this first step should be pretty simple so let's jump back into the memory cat component and look at the rest of the challenge in here I want you to start out by refactoring the code inside the Callback function of the map method that is this code here right now the Callback function is implicitly returning the list element I want you to change that and instead make an explicit return using the return keyword when you're done with that I want you to do some more work inside of the Callback function you should use selected cards that you receive as a prop to check if the card that is currently created here is selected or not and store the result of this check in a new variable called selected card entry and similarly use the match card prop to check if a card is matched and store the result of that check in a variable called matched card entry I do have a hint for you as well if you're not quite sure how to solve step three and four then go back into the app component and take a good look at the turn cut function you will find help there so go ahead and pause the scri now jump into the code give it your very best chart and return back to me to see my solution okay I hope that work well let's start in the app component all there is to do in here is simply to add some more props to the memory card so right here after the data prop we can say selected cards and set the value of this to be selected cards and the same for the second property we call the prop matched cards and set its value to be matched cards one last thing that I would like to do is to improve the readability by formatting this code a bit better now each prop is written on its own line and in my opinion this code is a lot more readable than the one we had before with this out of the way we can go back into the memory card component and receive these props to do that we simply add selected cards and matched cards charts up here right after the data prep the next step is now to refactor the Callback function inside of the map method first of all we need some curly braces here and of course we need to move the closing bracket down below the list element that we're returning and we can move the closing bracket of the map method one line up and place it here right after the closing curly brackets of the function itself in order for this to work we also need the return keyword so we simply say return and then we wrap our Li element inside of brackets again we need to move the closing bracket down below the Ali element and finally we have some formatting to do here now we have an explicit return using the return keyword and the formatting and indentation is just as it should be this allows us to write more code inside of the Callback function here inside the Callback function and above the return statement we can now create these two new variables and as I wrote in the hint here we actually already have a solution to how we can write this code inside our app component here in the turn card function this line of code is identical to the code we want to write inside of the memory card component so I'm just going to copy this one go back into the memory card and paste it in here and just because I'm lazy I'm going to do the exact same thing one more time and in this case simply change selected to matched and this should be it for this challenge at this stage there's still no change whatsoever to the app itself but we want to make sure that we didn't break anything so let's run the code and see that we don't get any errors we can start the game and we see our emojis rendered as before and clicking them does not cause any action visible to us and this is good because this means that there are no errors screaming at us at this point excellent we are now one step closer to get this conditional styling up and running and whenever you're ready I'll see you in the next room while we'll keep moving forward as you probably remember our goal with all the hard work that we are doing currently is for each memory card to really know everything about itself each card needs to know if it is selected or matched in order for us to be able to conditionally set the content and styling so far we have ensured that this information is available to us inside of the memory card component but we are not yet using it though as you might already have figured out by now this is about to change cuz in this scrim will finally go from always revealing the Emoji on all memory cards to actually turning the cards and displaying the Emoji only when a card is clicked and when I say we I do of course mean that it is time for you to write some more code please give me a second while I paste in the next challenge for you in order to solve this challenge there is work to do in here in the memory card component as well as in the Emoji button component to start with I want you to pass selected card entry and matched card entry as props to the emoji button and those are of course these variables here that you created in the previous scrim inside the emoji button component you should of course start out by receiving these variables next your job is to create a brand new variable called BTN content short for button content and then use selected card entry and matched card entry to conditionally assign a value to this button content if a card is either matched or selected button content should be the value of the content prop and otherwise it should be a question mark finally I want you to render button content as the content of the button and just to be completely clear the content of the button is is this so instead of rendering the content prop you should render the button content variable I do have a hint for you as well to solve step two you can use a Turner operator we are back in the memory card component where your heart work will start pause the scrim now do your very best to solve this Challenge and return back to me when you want to see my solution okay I hope that went well at this stage in the course this first part of the challenge should not cause you too much of a headache all we have to do is pass some more props so down here right below the handle cake prop we will simply add selected card entry and set the value of this to be selected card entry and we do the same for the Matched card entry sweet and simple that was the solution to Step One of this challenge let's jump into the emoji button component to finish this up first of all we need to receive these props so we say selected cards entry and matched card entry with these props added this part of our code up here where we are declaring the function and receiving props is getting pretty hard to read so let's just take a second to do something about the formatting so that was was a lot better now for step two here our task is to create this new button content variable and conditionally assign it a value depending on whether the card is selected matched or neither we start out by declaring the variable itself saying con ptn content and now the way I decided to solve this one was by using a combination of a Turner operator and the logical or operator so I start out by saying selected card entry and here comes the logical or operator and then match card entry what this does is that it asks whether selected card entry or match card entry is truthy and if either of these is truthy the expression as a whole will be truthy so this is the question we'll ask when using theary operator is the card either selected or matched if yes we'll assign the value of the prop content as the value of this variable button content then we add a colon here to be able to add an alternative value in case the card is neither selected nor matched and the alternative value should be a question mark finally we want to of course render this new variable as the content of our button we do that down here this should be it for this challenge let's run on the code cross our fingers and see how this plays out now to the Moment of Truth we start the game and we get question marks all over the place we are no longer revealing the value of our memory cards from the very beginning of the game but let's hope that we still do when we click one of these we ought to give it a try to check that it works it does look at this now what happens when we click your third card here the two first are turned back and showing just question marks this is absolutely amazing we're not quite done yet the content is in place but our styling is still not quite the way we want it to be we still have a bit more work to do but nevertheless this is indeed a milestone in our memory game so congratulations if you managed to complete this Challenge on your own take a break if you need it go for a walk drink a cup of coffee or just celebrate your victories and when you feel refreshed and ready to move on I'll see you in the next RM it is finally time now to finish up the conditional styling of our memory cards in the previous scrim we managed to conditionally set the content of each card and in this scrim we'll focus on conditionally setting some class names though before I give you your next challenge there is one small change that I would like to make to our emoji button component you see this style prep here a few scrims ago when we created this component I explicitly told you to write your code this way and I did that because I really wanted you to practice passing and receiving props but now we're actually going to delete this prop entirely inside of the component itself here the emoji button we need to delete the style prop since we're no longer receiving it and then we want to change the value here on the class name instead of this St prop will simply hardcode the class names my reasoning for making this change now is that I want to handle all styling inside of the emoji button component itself instead of having some of it being passed as props and other parts of it being created here in the component with this out of the way let's go back into the memory card component where I will give you your challenge there are four steps to this one but in a way you could actually say that there are just two steps tabs that you'll repeat twice with slight variations in the repetition in here in the memory card component I want you to create a new variable called cart style and conditionally assign it a value depending on whether incart is selected matched or neither the values that you'll be assigning to cart style are class names and I have of course written out all the class names you need to use right here so that you can copy paste them when you've done that you should take this new cart style variable and add it to the existing class on the LI element the second half of this scrims challenge is written out inside the emoji button component in here I want you to do something very similar to what you just did create a new variable called button style and conditionally assign it values depending on whether it is matched selected or neither and this time you should use the class names I have written out right here and just as before when you have this button style variable up and running I want you to add it down here to the existing classes set on their button I'm aware that this challenge might be a bit tricky so I did provide some extra help for you as you can see I have a hint for step one and three and I've also written out what the visual result of all your hard work should be so that you can double check that all the styling that I already wrote in the Cs file is actually applying go ahead and pause the scrim now do your best to solve this one and I'll be back with you in just a second to show you my solution okay I hope that went well let's get to work on the memory card the first thing we want to do in here is declare this new variable I decided to do this using what we call chained or nested Turner apparatus and therefore I can go ahead and use the count keyword when declaring my variable if you used a lead variable and if else statements that is completely okay just as with a regular turn operator we start by adding a condition here and what we need to check first is if a card is matched to do that we can use the match card entry and after typing out the condition we add a question mark after the question mark we provide the value that we want to assigned to button style in case match card entry evaluates to true and that value is of course card item matched so I copy it from up here and paste it in here so far this looks exactly like a regular tary operator what's so special about the Nesta ones is that now after a colon we add a new condition this time we want to check if a card is selected so we write select a card entry then a question mark and pay in the correct class name finally we provide an alternative value in case the card is neither selected nor matched and that value is simply an empty string as far as I know the general opinion on nested or chained Turner operators is that we should be a bit careful using them and that is simply because they can be quite hard to read in our particular case I think that this readability issue can be solved pretty easily by just for formatting the code a bit better now as you can see we have each condition and its corresponding value on separate lines and this is at least to me a lot more readable code now onto step two all we have to do is to add our new variable to the class name on the Ali element and I just realized that clearly I had button Style on my mind because I wrote BTN instead of card here let's just fix that okay back to the class name what we have to do down here is first of all change the string to a template literal we do that by removing the double quotes and instead we want back tis though the back tis themselves Aren't Enough here we also need to wrap the entire expression in cly braces this gives us a valid template literal instead of a string and we can now use the dollar sign and color braces to add cut style in here and this was it I believe for step one and two of our challenge in the emoji button component our job was as I explained to do more or less the same thing if you struggled solving this challenge or if you solved it using lit variables and IFL statements I would highly encourage you to try to solve step three in here using the nested Turner operator syntax simply because it's such good practice to get your hands on the keyboard writing code so if you feel like you need it pause the scam now and try to finish the rest of our Challenge and I'll be back with you in just a second okay let's finish this up we create the new variable and this time it is actually button style we need the exact same conditions as we had inside of the memory card so we say match card entry and if this evaluates to true we take the class name here that we want to add to match cards and paste it in after the question mark then the colon and the second condition which is again select a card entry the question mark and the class name that we want to add to selected cards and finally after the color we want the class name for cards that are neither selected nor matched just as before I'll do something about the formatting here and all we have left to do now is to add this button style variable to the class name on the button again we remove the double quotes add back taks wrap the whole expression in curly braces and use doll sign and colly braces to add button style and this should be it for the entire challenge I'm going to delete almost everything here but leave the description of the styling just for you to be able to reference it now let's run the code and see how our styling looks now we start a new game as we've done so many times before and you see now we get these wonderful horror effects the background color changes to some light yellow we have a bu Shadow and if I click a card there is this slight animation as if the card is actually flipped or turned now I'm going to check the focus styling just for the sake of completion so I use my Tab Key to go one step forward we have the exact same styling as we did on Hover I can use my Enter key to turn this card and everything seems to be working one last thing we want to do is find a matching pair so we can check our match card styling is also applying I believe we had this goat here I'm not sure let's see we did now you can see the background is grayed out and when I hover over one of these match cards I can see that my cursor is not allowed I'm aware that you cannot see that on your screen but try to do it yourself hover over these match cards and see what a cursor not allot looks like this is absolutely amazing we are done styling our memory cards there is one last thing that I would like to point out to you before we move on in the challenge I told you to be careful about the order of the conditions when we set the value on our button style and our cart style variables we have to check for match cards before we check for selected cards and the reason is that in a situation like this one where we have just found a matching pair these two cards are selected SED and matched at the same time so since we want them to get the match card styling as soon as they are matched we need to check for that condition before we check if they are selected in the next SC we'll look at some small but important details on our memory cards so when you're ready for that I will see you there as I announced in the previous scrim we'll Now work on a couple of details in the emoji button component and in the turn cut function first of all will improve the user experience by disabling the emoji button whenever a memory card is matched due to the styling that we applied in the previous scrim match cards look as if they were disabled but actually they are not they have this very classic look of a disabled button with a grade out background and a cursor that is not allowed but in fact these match cards are as clickable as any other card in the game we can prove this by adding a console log in here in the turn car function let's run the code again start the game and just click till we find our first matching pair as I'm sure you noticed we got the word clicked locked to the console every time I clicked a memory card and notice now that when I click a Mac card this cute squirrel or whatever it is down here we still get the word clicked lock to the console meaning our turn cut function is still running though this is to be honest not a very good us experience and your next challenge will of course be to fix this by making the button on our matched memory cards disabled there is just one single step to this challenge I want you to add a disabled attribute to the button and give it a value that is truthy when a card is matched otherwise falsy I'm not going to give you any hints here because I believe that you can do it but if you're struggling and need some extra help you can always ask Google or chat GT remember there's no shame in doing either of that pause the scrim solve this Challenge and return to me to see my solution all right hopefully that went well let's fix this one together right here on our button element below the unlick event handler We'll add a disabled attribute and we want to give it a value that evaluates to True when a cut is matched otherwise false luckily for us we already have a variable available to us right here inside of the emoji button component that does exactly that and that is of course the Matched card entry let's run the code again to see the difference here I'll speed up now and find our first matching pair well that was an easy one the two first cards were a match we still got the word clicked lock to the console when we turned this card but look at what happens now if we click one of these nothing at all the console log is not running meaning the turn cart function is not called there is one more thing I want to show you and actually I need to find another matching pair to be able to show you that due to the position of these two cards give me a second okay this will do because we have disabled our match cards we have also ensured that these cards are not focusable meaning they will be skipped when we use our keyboard to navigate through the memory cards I'm now going to turn this card here number four of our memory cards and then use keyboard navigation to move forward I hit my Tab Key once that takes me to the cut right next to it then I hit my Tab Key again just once and now our Focus ends up down here after this match card because it is skipped by keyboard navigation so we have now successfully pulled our match cards out of the memory game to allow the user to focus only on the cards that are actually still part of the game our second task in this scrim is to improve the code efficiency let's go back into the app component and take a look at our turn card function here one more time as I'm sure you remember we explicitly wrote the code here inside this function to run conditionally only if the clicked card is not already selected this works perfectly fine honestly but since we really don't want anything to happen if the user clicks and already select a card we might as well not call the function at all when they do so therefore I'm going to delete those parts of the code that have to do with the selected card logic we can delete the selected card entry variable and inside the if else blogs we will of course also delete this check to see if selected card entry is a falsy value you now if we leave the code like this and do nothing more our memory game will be broken because one and the same card can now be selected more than once so it will now be your job to implement the same kind of conditional logic inside our emoji button component your challenge is to refactor the onclick event handler right here on our button element you should use a turnover operator to set the value to null if a can is selected and otherwise handle click you should write your code right here on the event handler itself inside of the curly brackets but before the handle click function reference pause the scrim Now work on this Challenge and I'll be back with you in just a second to show you my solution okay I hope that went well let's do this together what we want to achieve here is to not call the turn cut function in case we click a card that is already selected therefore in the Turner operator that I told you to use the condition that we want to check for is of course if the card is selected and we do that using the selected card entry variable to ensure that handle click is not called in case selected card entry evaluates to true we add the value null after the question mark and if selected guide entry evaluated to false we do want to run handle click so all we have to do now is add the Sten to get the correct turn re operator syntax and that was it let's run the code one more time to see how this went we turn our first memory card and we get the word clicked lock to the console now I'm going to click the same card one more time and nothing happens excellent this was exactly what we wanted our game logic is back on track we simply move the conditional logic from one place in the code to another what we win by refactoring our code in this way is that we avoid unnecessary function calls there is no reason at all to call a function if we already know an baned that we don't want that function to do anything in case the click card is already selected it's a lot more efficient to make that function call itself conditional All In All by adding the disabled attribute and refactoring the event handler we have now ensured that our turn C function is as clean and readable as possible because all the conditional logic is handled right here inside our button component and in my opinion this is cleaner and more readable code with these refactoring done we are ready to move on to the next Grim where we'll start looking at how we can make our memory game accessible to all uses when you're ready I'll see you there accessibility is a very important aspect of front end development the apps and websites that we build should be accessible to any us user some of the things that we need to consider are for instance can the user navigate by means of both mouse and keyboard do we have proper color contrast and is all content available in a clear and hum intelligible form both visually and to assistive technology like screen readers in order to ensure the accessibility of our apps we have various tools at hand and two of these are the area label and the area live attributes they can be used separately or in combination and when used in combination what they do is that they ensure accessibility by adding humanly intelligible information to otherwise inaccessible elements and determine when screen readers should read a this information we will now take a closer look at them one by one and see how they can be useful to us in our memory game first we'll talk about the areial label attribute in the mdn web docs the role and function of the area label attribute is described like this in cases where an interactive element has no accessible name or the accessible name is not accurate the area label attribute can be used to define a string that labels the interactive element on which it is set you can click the link right here if you want to go to the MDM web docs and read more on your own so when should we use areal labels the short answer is when we have no other option just to give you a rather contrived example we should not create apps that uses icons instead of clear and descriptive text all over the place on every single button every single link and then afterwards add areial labels to fix the accessibility issues that is not the purpose of the area label on the contrary the purpose of the area label is to provide additional information to assist of Technology about the content of some element when there is basically no way of having this information visibly available in the amp and how do we use that then well I have come up with an example here to illustrate as you know in our memory game the visual or visible content of our buttons that are rendered on each memory card is an emoji just like the cute little monkey face here as you also know these emojis are actually HTML entities that we then decode when we render them to the screen this means that the default accessible name on each and every one of our buttons is the HTML entity so if our user for instance rely on a screen reader to navigate through our app and understand what is on each button all they'll get is the HTML and that really isn't human friendly to fix this issue we can add aerial labels to our buttons describing the rendered Emoji our little monkey friend here has a name in the world of emojis and we can take this name monkey face and set it as the value of the area label in this way we ensure that when our user encounter a monkey face they get the string monkey face read allow to them next up is the Arial live attribute this attribute controls when a screen reader should read alloud the content or ARA label set on an element it takes one of the following three values of which is the default polite and assertive the difference between polite and assertive has to do with well politeness if we set the areial live attribute to assertive this means that the screen reader will interrupt any other activity or action that is going on in the app to read allow the area label that we set on that particular element often that is not a very good idea it can be useful in some situations but it's much more common to use polite because polite Waits politely for the right timing and when there's nothing else important going on the screen reader enters the scene with this new information politely and when should we use this AAL live attribute then the attribute is used to make Dynamic content changes available to assistive Technologies to understand exactly how this works and how we should write our code I've come up with another example for you here we have an HTML button element that is rendering a question mark you probably recognize this from our memory game but we also have an HTML button element that renders a question mark on this button there is an area label with the text card upside down this information is needed because the question question mark itself is not really what I would call humanly readable and intelligible information about the button what does question mark on a button mean when you can just use your eyes and your vision to look through a memory game it's quite easy to understand this question mark But when you can't it doesn't really make sense so we add the area label card upside down to provide information about the status of this memory card below the area label there is an area l five attributes set to polite as you very well know when this button is clicked in our memory game the content of it changes suddenly we have a button rendering an HTML entity instead the area label has to change to match this HTML entity and the area life is still polite we're not going to touch that the combination of the area label and the aial live in us two things here as soon as the user focuses one of our butons the areal label is read alow when the user then turns that memory card the new areal label is read allow because the areial life attribute is set to polite and not off which is the default now let's go into the code editor and take a look at these accessibility Tools in action I have created this very basic and very boring app that mimics the functionality of our memory game in this app we have just one single button and when we click it the content on it changes from a question mark to a monkey face and if we click it again it changes back to a question mark the button is rendered right here inside the return statement of our app component on this button we dynamically set the content using the content property from the state variable BTN value the state variable is declared up here at the top of the component it is initialized as an object with the content set to a question mark and the area label set to the string cut upside down back on the button we also have an unclick event handler that calls the function set button content inside of this function we use the Seto function from state to toggle both the button content and the error label back and forth between question mark and monkey face right now this button lacks when it comes to accessibility because the default accessible name is the content on the button so it's either a question mark or it's an HTML entity to fix this we need to add both an areial live and an areial label attribute to the button areial live is the easiest one of these two we simply set the value to polite on the area label we want to use the area property on our BTN value object that we save in state so we type out BTN value. area together these two area attributes ensure that whenever the value of the button changes the updated area label will be presented to users of assisted Technologies when we set the value of the area label attribute on an element there's one last thing that's really important and that is to always finish off the string with a period the period at the end is a signal to the screen reader that it should pause for a little while before moving on and reading out whatever is next in line to add this period we have to turn the value on our area label into a template literal and we do that by adding back taks and an extra set of curly braces around these btics now we have a valid template literal so we can add a dollar sign in front of the variable and a DOT at the end in order to properly test that our code is working we would need to have a screen reader installed turn that one on and click our button to hear what it reads allow and if you happen to actually have a screen reader installed I highly encourage you to go ahead and do that though if you don't that's completely fine and what you could do instead is to open up your browser developer tools and inspect the button element on this element you should see that the Aral label changes whenever you click the button and the content of it changes in the next Grim we will return to our memory game and use everything we've just learned to make our memory cards accessible so when you're ready for that I will see you there in this scrim we'll take what we just learned about the area label and aial live attributes and apply it to our memory game though before we get going there is one small change that I want to make to our emoji button component right now we are passing this content prop and we've set its value to be the decoded HTML entity which we then use inside emoji button to render the Emoji instead of doing it like this decoding the HTML entity here we're now going to pass down the entire Emoji object I'm going to leave the content prop here for a little while just for us to reference it and then right below it create a new prop called emoji and then pass in the Emoji object as its value in the emoji button component we'll receive this Emoji prop and then we'll use it right here instead of the content prop when we create the conditional values of the button content just as we decoded the HTML entity before inside the memory card we'll now do this decoding inside the emoji button so we can actually just copy this line of code go back to the emoji button component and use that instead of the content prop and since we're now using the decode entity method here we also need to import that into our component again we can do some copy pasting we simply take the import that we've written up here cut it out go back to the emoji button and paste it in here and now we should be able to delete the content prop entirely here where we are receiving it and in the memory card while we are passing it down let's just run our code to make sure we didn't break anything here we have our memory cards lying face down and when I click one of these we still see the Emoji rendered great that means that everything is still working the exact same way as it was before the reason why we're doing this refactoring is because we need access to the entire Emoji object inside of the emoji button component to make those buttons accessible as you know we can use the area label to make information about an Interactive element available to assistive Technologies but exactly what information should that be in our case before I answer that question I want you to think about it on your own so I have prepared A Min challenge for you you don't have to write any new code now what I want you to do is simply to think and come up with an answer to this question what information about each memory card does the user need to be able to play our game pause the scri now and give this some thought okay did you figure it out let's look at the game together right now we have 10 cards rendered one of them is turned and showing a turkey and the rest of them are lying face down by just looking at this I can see that there are 10 cards I can see that it is the very first card that is turned and I can see what value is on that card if I turn another card I'm just going to take a random one down here for instance I can now see that that shows a koala and I know where this card is positioned relatively to the rest of the cards relatively to the turkey to be able to find matching pairs in here I need to remember where I found this koala and where I found the turkey so that means that I need information about the value and the position of each cut now that we've got that cleared up it is time for your next proper coding challenge there are four steps to this challenge the first one is written out in the memory card component this one is pretty simple you should pass the index as a prop to the emoji button then back in the emoji button component I want you to create a new variable called button area and conditionally assign it a value depending on whether the card is matched selected or neither I have written out the values that you should use here but as you can see on matched and selected cards I'm simply telling you that you should show the name of the Emoji but I'm not telling you how you should do that when you've created this button area variable I want you to set an areal label on the button the value you give it should inform about the position of the card and also contain the button area in case this feels a bit confusing I have given you an example right here of what it is I want you to do for instance an area label could say position one colon monkey face period not matched yet period finally I want you to set an aerial live attribute on the button and give it the value polite I do also have a hint for you you can use the index prop that you're now receiving to determine the card's position but do remember that humans start counting from one not zero go ahead and pause the scrim now do your very best to solve this Challenge and return back to me to see my solution okay hopefully you managed to solve this challenge let's get to work in the memory card component all we have to do here is to pass the index as a prop to emoji button we call the prop index and give it the value index back in the emoji button component we receive this index prop and then we start working on step two where we are to create a new variable called button area I'm going to stick to my nested Turner operators so I can say const button area and then make my first check to see if the card is matched if so I want the value to be the name of the Emoji and the word matched to be able to combine these two I'll create a template literal then I add in the name of the Emoji using dollar sign C Braes and as we know on each Emoji object we have a name property then I put a period here and write the word matched and of course it's super important to remember the period after the last word in the string I happen to know that an emoji name can contain HTML entities because things like apostrophes are represented with HTML entities in the API that we're using so to make sure that our Emoji name is actually humanly readable we have to decode that one as well so I wrap it in Brackets and use the decode entity method if match card entry evaluates to false I want to check if the card is selected and if so I'm going to do pretty much the same as I just did up here so I'm going to cheat a bit now copy this bit of the code and paste it in down here and instead of matched I'll simply write not matched yet and finally if the card is neither matched nor selected the value that we want to set on button area is card upside down in step three we are to set an area label on the button we can do that right here below the disabled attribute and from the example that I gave you we know that we want to write out the word position and we also want to use some variables here so we need a template literal again therefore we start with back Tex then we can type out position and use the index here as you know the index of the very first item in an array is zero not one and humans tend to start counting from one and not from zero when they see 10 memory cards rendered to the screen so we have to say index plus one to make sure that the first card actually gets position number one now we add the colon and we add in the button area finally we create an area live attribute and give it the value polite like this this should be it for this entire challenge if we really want to make sure that this is working we have to use a screen reader but since I already double check this a ton of times I think it's good enough if we just check that we get no errors and then you'll just have to trust me that this will work the way we intend it to if we turn on a screen reader and play a memory game but let's at least run the code to check that nothing is broken we start the game we click some cards and we get no no errors screaming in our faces so everything seems to be good awesome we just made a huge Improvement to the accessibility of our memory game and you should be very proud of yourself for working on this challenge solving it the best you could and now knowing a bit more about accessibility when you're ready to move on I'll see you in the next scrim in order to avoid potential confusion regarding the state of our memory game I have decided to rename one of our state variables namely this one here is game over the core functionality of this state variable is to keep track of when all memory cards have been matched and after some consideration I decided that it would be better if the name reflected this functionality so now I'm going to rename it to are all cards matched I don't want to go into too much detail about why I think this change is important simply because the potential confusion that I was talking about lies in the future but what I can say is this I realized that having both an is game on and is game over State variable was not really intuitive or logical and since we do need both of them the obvious solution was to improve the naming of one of them it is definitely not one of my proudest moments to interrupt my own course with such a change but as you know coding is a NeverEnding work in progress very often we learn as we go and the best thing we can do is to incorporate changes and improvements to our code as quickly and openly as possible so that our fellow devs can easily follow along and understand our work so with this out of the way we are ready to move forward again in this scrim we're going to create a brand new component called assistive Tech in we need this component to further improve the accessibility of our app making the memory cards themselves accessible as we did previously is by far the most important part of the accessibility work we have to do in this project but it's not the only part so what is this new component going to do well it's going to provide additional information to uses of assisted Technologies informing about the game status to illustrate what I'm talking about here I'm just quickly going to start a new game and find some matching pars when I play this game I can see how many cards are matched and how many I have left to match in this case for instance we have at this stage two match Pairs and six cards left to match for sure I can live without this information this is not what will make or break my game Flow but I must say I'm really glad to know this because it sort of gives me an over view of where I'm at in the game users of assisted Technologies don't have immediate access to this information unless they tap through all the memory cards and still even if they do so they will have to do some math afterwards because as you very well know the match cards are disabled and therefore skipped when we navigate with our keyboard because we are smart and attentive developers we know that this is not a great user experience which is why will of course make sure to give all users access to all relevant information about the game status so now that you know why we need this new assistive Tech info component it is time for you to actually create it here is what I want you to do in this challenge first you should create a new component inside of the components folder and call it assistive take info the component should take two prompts Emoji state and match counts and it should return a section element containing one H2 and two P elements the content of these elements the H2 and the piece is written out right here as part of Step One in step two I want you to render this new component between the form and the memory card that is down here in this space I just created for you and you should render it conditionally when is game on is true and are all cards matched is false and do of course remember to pass down the props in step three I want you to play a memory game to check that everything is working both the dynamically updating content and the conditional rendering of the component and when you're sure that everything is working step four is to add the class Sr only to the section element inside of the assist of tech info component to hide it from the window for now please don't worry about setting any area attributes on the new component we'll be working on this in future scrims pause the scrim Now work on this Challenge and return to me to see my solution all right hopefully that went well let's get to work we'll start by creating the new component inside of the components folder we know that we want to export a component from this file so we'll start by saying export default then we'll declare the function and call it assistive Tech info in here we want to return a section element so we'll start with a return keyword open up a set of brackets and then create a section element inside of the section we want an H2 and two P elements before we can finish our component here we need access to the Emojis Stater and the match cards array that we have saved in state so we know we want to receive those as props I chose to again destructure my props object directly here inside of the brackets to get the number of match Pairs and display it here on the first P tank we can take the match cards array which contain all of our match cards and then divide it by two because we want to show the number of matched pairs to do that we add curly braces and then we say match cards do length and divide it by two similarly when we want to know how many cards we have left to match we do some math involving both the Emojis data and the match cards we know that we have a total of 10 memory cards because we have 10 emojis in our emojis data and if we subtract the match cards from the Emojis sta we get the number of memory cards that are not yet matched so again we open up the color graes and this time we say emojis data. length minus match cards. length let's go back into our app.jsx and import this new component we do that up here right below our other Imports so we say import assistive Tech info from the components folder and the assisted Tech info file oh and I see I made a typo here assistive Tech info now that we've imported it we can render it right here we know that we want to render it when the game is on and when the bullion are all cards matched is false so now after this second logical and operator we simply type out our component name our component is receiving the props emojis data and match cards so let's make sure that we actually pass those props and finally just to make sure that this is still readable we'll do something about the formatting okay I think that was a lot better that was I believe step one and two of our challenge now step three is to play the game and check that everything is working now when we start a new game we get this game status section rendered above our memory cards right now our game status is that the number of match pairs is zero and the number of cards left to match is 10 let's find our first matching pair to check if the value update correctly here we had a matching pair and now our game status is correctly showing that the number of match pairs is one and number of cards left to match is eight to make sure that this section disappears again when all the cards are match I'm just quickly going to go through this game and match all of the pairs okay this is the moment of truth I have one C left to turn when I turn this card the game status section should be hidden again and and it is excellent that means that our conditional rendering is working and our dynamically updating content inside of the section is working as well the fourth and final step of this challenge was to add an Sr only class to the section element in the assisted Tech info component so right here on the section we say class name and Sr only Sr is short for screen reader the whole point is here that we don't need to display this information visually on the screen but we need to keep it accessible to screen readers which is exactly what the CSS I have written on this Sr only class is doing and you know what I think that we should actually take a quick look at the CSS together here we have it the SR only class and as you can see there is a lot more to this than just setting the display To None or set visibility to Hidden if you want to hide something like really hide it so that nobody will ever find it then go ahead and use one of those display on a visibility hidden but if you want to hide something only visually and keep it accessible to assistive Technologies this is one of the better ways to do that I did not come up with this Solution on my own on the contrary I found it here on the source that I am linking to I highly encourage you to check it out on your own or as the very least keep in mind mind that hiding things from the screen should always involve considerations when it comes to the accessibility of what it is your hiding with that said we are ready to move forward and in the next Grim we'll do a bit more work to make sure that this component really is accessible in the way that we want it to be see you there in this scrim we'll take a look at another one of our accessibility tools namely the area atomic attribut in the mdn web dos about this attribute which I have by the way linked to right here it is described like this when the content of a live region changes the Dom is traversed from the changed element through its ancestors to find the first element with area Atomic set this determines the content that the user should be presented with if no ancest has explicitly said area Atomic only the note on no not of live region content that have been updated are read this is quite a thorough and accurate description but what exactly does all of this mean well let's try to break it down into something that is hopefully easier to understand first of all why do we need this area Atomic attribute when we're dealing with areal live regions the areal live attribute controls if or when assist of Technology should present dynamic changeed content to the user by default only the changed content is presented even when aial live is set to polite or assertive in this context we could say a bit simplified maybe that an aial live region is some content that is grouped together some of this content changes dynamically for instance through user interaction and some of it does not and if we in this situation rely only on the area live attribute as we talked about in a previous scrim the static content will be omitted so if it's important that the static content is read aloud together with the dynamically changing content we have to find a way to let assistive technology know that this entire region should always be read aloud with all of its content and that is exactly where the area Atomic attribute comes into play with this attribute we can take control of this default Behavior where only the change content is presented and instead decide if unchanged or entirely static content should be read aloud too and how do we use area Atomic then we set the attribute on a live region for instance a div or a section that is containing dynamically changing content the attribute takes either true or false as its value if we set the value to true the entire live region is treated as a single unit and all content whether static or dynamic is read allowed whenever any part of it is changing if on the other hand we set the value to false the region is not treated as a unit and only change content is read allowed one more important thing to know is that if we don't set an area Atomic attribute at all the outcome will basically be the same as if we set it to False only the changed content will be read a lot I have of course prepared an example that illustrates the use of the area Atomic attribute but before we get to that let's just quickly recap the area live attribute the buttons that you see here are not new to you I copy pasted them from the slide about area live and what they illustrate is one and the same button with changing content and a changing area label when the button first renders we see a question mark that is the button to the left here and when we click it the content changes to an HTML entity and the area label changes from Cut upside down to monkey face since we have set the area live attribute to polite here the changed area label will be read aloud whenever this button is clicked and the content and area label is changing if we take this very same button and place it inside of a div together with some static content in this case an H to rendering the string static heading we will have to consider which parts of this content we want the assisted technology to present to our users on the dev to the left here there is no area Atomic attribute meaning that whenever we click this question mark button and the content and area label of the button is changing only the area label set on the button will be rent allowed the static heading will be skipped if we on the other hand set area Atomic to true all content inside of this diff will be treated as a single unit and everything will be read aloud I have once again created a very simple and super boring app to illustrate how this works our question mark button here that has the same effect as you've seen before we click it and the content changes to a monkey face we click it again and it turns back to question mark this button is placed inside of a container a div that I have styled here with a border so that you can see exactly what is part of this div the div you can see is rendered right here and apart from that the rest of the code is more or less identical to what you saw in the scrim about the areial label and area live attributes our H2 here the static container heading is absolutely crucial without this heading our user will be completely lost when it comes to understanding what is going on with the button inside of the diff and therefore we must ensure that assist of Technologies read allowed our static container heading together with the changing values on the button to do that we go up here on the div and we send the areial live to polite and we set the area Atomic to true now we have ensured that everything inside the div is treated as a single unit and that all content is read aloud when every parts of it is changing with this new area Atomic attribute under the belt we are ready to return to our memory game and work on the accessibility of our new assistive Tech info component see you there now that you know how the presentation of live region content works and what tools we can use to control it let's just get straight to work here in the assisted Tech info component first I have a mini challenge for you I I want you to try to come up with an answer to the following question which parts of the content in this component will be read aloud when there are Dynamic content changes and which will not Pastor scrim now give this some thought and return to me to hear my answer to this one okay do you have an answer ready for me no matter what I have an answer ready for you and the answer is nothing nothing at all will be read aloud this was in fact a bit of a trick question and that was of course deliberate since no parts whatsoever of the content here will be read aloud when there are Dynamic content updates and that is simply because we didn't do anything to prompt screen readers to do that so if we leave the code as it is now all of our hard work with this component will be in vain because the information that we are trying to convey to the user will never be presented to them by assisted Technologies luckily you know how to fix this so without further Ado I'm going to give you your next proper coding challenge in this challenge I want you to fix the issue that we just discussed you should turn the sectioned element and its children into a single unit and prompt assist of technology to present all content of this live region to the user whenever parts of it change pause the scrim now and work on this Challenge and I'll be back with you in just a second to show you my solution all right I hope that went well all we have to do here is to go down to a section element and add an areial live attribute with the value polite and an area Atomic attribute with the value true with these two attributes added the entire section with all of its content will be readed by screen readers whenever any value rendered inside of it changes now you might think that this challenge was so basic and simple that it was a bit silly of me to even make it a challenge but as I'm sure you heard before getting your hands on the keyboard and writing code is by far the best way to actually learn to code you learn by thinking and by doing not by watching me do it besides coding doesn't always have to be painfully hard work every now and then it's okay to just Implement some quick fixes and have a good time when you're ready to push forward with our memory game I'll see you in the next scrim in this scrim we are once again going to create a brand new component the component we'll create this time is to pob up above the memory cards when the user has matched all memory cards in two pairs and you know what I don't think that I actually need to say anything more to prepare you for your next challenge so let's just get to it here is what I want you to do go into the component folder out here on the sidebar and create a new component called game over this component should return a div containing a p element right here as part of step one I have written out what content and styling you should set on the div and the P element in step two I want you to render this new game over component right here and you should render it conditionally when the state variable are all cards matched is true finally I want you to play a memory game to check that the conditional rendering of this component is working pass the scrim Now work on this Challenge and return to me to see my solution okay hopefully that work well let's do this together first of all we'll create the new component out here in the components folder and then in here we write the basic sent tax for our game over component we'll make a default export here and inside of the component we'll start with a return keyword and what we want to return is a div element and inside of this we want a p element now to get these styling and content in place I'm just going to speed up and do some copy pasting there we go The Styling and content is in place let's go back to the app component to finish the challenge we can delete step one here and in step two we want to render this new component in order to render it we do of course have to import it first we'll do that up here together with the rest of our Imports so we say import came over from and it lives inside of our components folder in the final game over now we can scroll back down to the return statement and render the component here between the brackets the condition for rendering this one is that our all cards matched has to be true so we say are all cards matched and then use the double m perent and now we render an instance of game over the only thing we have left to do now is to play a game and check that the conditional rendering is working now let's run the code start a new game and I am going to speed through this one okay here we are with one card left to turn this is the Moment of Truth we turn the last card and look at that our new game game over component is appearing just as it should conditionally when all of the cards are matched so far so good though we are not quite done with this component yet cuz we want to also add a button to it allowing the user to play a new game if they want to to fix this we'll need to write some more code inside the game over component and we'll also need to create a new function here in the app component when you're ready to move on I'll see you in the next scrim as I announced in the previous Grim we want to add a button to this new game over component that we are rendering here this button should reset the game and bring the user back to the form that we're rendering when our app first loads I am not going to say more right now about how we can reset the game because I want you to try and figure that out on your own so what are we waiting for let's get going with your next CoD challenge in step one I want you to create a new function called reset game as the name indicates the function should reset the game but it should not modify emojis data or interact with the Emoji Hub API in any way in step two you should pass this new function to the game over component as the value of a PR called handle click when you've done that I want you to go into the game over component and here you should render an instance of the regular button component right below the P element that is right here where I have just created a space for you and remember the regular button is a component that lives out here in the component folder the regular button should receive handle click as a prop and remember you just pass down that prop from the app component to the game mode component so now you're going to pass it one label further to the regular button and the content of this button should be play again finally in step four I want you to play a game and when You' finished you should click this new play again button to check that everything is working clicking this button should make the previous game disappear and instead make the form component render again if you're not quite sure what to do with this regular button component that I want you to use then take a good look at the hint I've written out for you here as well all right pause the scrim now give this your very best jot and return back to me to see my solution so I hope you managed to solve the challenge let's go back into the app component and get started together right here below the turn cut function we're going to clear the new function called reset game in order to perform this resetting there are some State variables that we need to set back to their initial State we know that we are not supposed to touch this one the Emojis data but apart from the Emojis data we actually have to set all other state variables back to their initial state is game on has to be set back to false both the selected cards and the match cards arrays have to be cleared set back to empty arrays and finally are all cards matched should be set to false I'm just quickly going to type out these set functions to get our reset game function up and running and that was it for our reset game function running this code here will hide the old memory game it will set all state variables related to the game mechanics back to the initial State and it will bring the form back to the mini browser in step two all we have to do is to pass down this new reset game function as a prop called handle click to our game over component so we say handle click and add reset game as the value that was it for step one and two now let's go into the game over component to finish the job the first thing we should do in here is of course to receive the prop that we just passed I didn't explicitly write this in the challenge and that is is just because I'm teasing you a bit I wanted to make sure that you are still awake so by omitting this information I forced you to remember it all on your own the next step is to render an instance of the regular button component to be able to do that we have to of course import it first so up here at the top of the file we say import regular button from the file regular button that lives here in the same components folder as our game over component to access this F now we start out with a DOT here to go one level up to the folder then we use the slash to enter the file and then we say regular button inside of the diff that we are returning we can now render an instance of this button you might have been tempted to render the button like this writing the component name only once and with the closing tag right after the name here and if you did you ran into problems right hopefully my hint was helpful to you in that situation let's take a quick look together at these two components that I was hinting about first the regular button itself here it receives two props children and handle click the handle click is what is being passed here to the onl event handler and the children is the content that is rendered on this button now to understand how we use instances of this component let's take a look at the form component as well here as you can see we are rendering an instance of the regular button component using both an opening rular button tag and a closing rular button tag and in between those we have this string here start game which is the content that is rendered on our phone button on the regular button opening tag here we have just one prop called handle click so by looking at how the regular button component is used used here inside the form we now know that the children prob received by the regular button component is the actual children rendered here between the opening and closing tags therefore back in our game over component we have to use the exact same syntax instead of this closing tag here at the end we need to have both an opening and a closing tag with the component name regular button the children that we want to pass is the string play again and the handle click prop is passed right here on the opening tag and we simply use handle click as both the name and the value of this prop that was step three done so all we have left to do now is to play a game and check that it is working once again I will just speed up and match these 10 cards into five pairs so now there is one card left to turn I click it our game over component turns up above the memory cards we have our play again button here and when we click it the memory cards disappear and we're back to where we started seeing only the form component to make sure that our code really is bulletproof let's just start a new game to check that we didn't mess anything up everything seems to be working still exactly as the did before amazing the reset game function that we are calling from this game over component is working perfectly just as we wanted to we do still have a bit of work to do on this game over component because right now it is unfortunately lacking when it comes to accessibility and as you know by now smart and attentive developers like you and me will not accept that we want all users to have a marvelous experience when they play our memory game so when you're ready to tackle your next accessibility challenge I'll see you in the next scrim the accessibility issue that we are facing here with our game over component is that users of assisted Technologies are not informed about the sudden appearance of this new component when I play the memory game and I turn the very last count here then because I can see what's on the screen there is an obvious change happening and my attention is drawn to the new game over component but when you can't see what's on the screen you are quite frankly lost here you don't immediately know that the game is over nor that there is a new button you can now click to play the game again in fact you'll have to use assist of Technologies to navigate through the entire app until you hopefully and totally by chance find the game over component previously when we fixed accessib issues we have used various area attributes to prompt screen readers to readal out parts of our app but this time that approach won't work you see all the content here on our component both on the P element and on the button element is static so telling assisted Technologies to look out for changing content just won't have any effect therefore we need a different approach here in the next GM we'll look into how we can use javascripts do Focus method to ensure the accessibility of this component see you there in this scrim we'll look at how we can add Focus to a new Dom element and thereby fix accessibility issues like the one we identified in the previous scrim unfortunately this is quite a bit more complex than it might sound in the previous scrim I announced that we can use javascript. Focus method to ensure the accessibility of our game over component and that really is true though the thing is we also have to use two different react Hooks and a global attribute to actually make this work but let's not dwell anymore on the scary complexity of the task at hand and instead just move forward and try to demystify it the issue that we are facing is this when a new element or component is rendered to the Dum it is not immediately presented to users of assistive Technologies the solution to this issue is to programmatically add Focus to this new Dom node and thereby prompt screen readers to read its content aloud as soon as it renders to achieve this immediate presentation by screen readers of a new download we need to use a cocktail of tools we need the react use RF hook the react use effect hook we need the javascript. focus method and the Tap index Global attribute as you can see each of these tools are styled here on the slide with a different text color and an underline and that is because all of them are links you can click them to get directly to the relevant documentation if you want to read more on your your own now let's talk about these one by one what do they do why do we need them first the react use ref hook in a react component we can use the use ref hook to create what is called a ref this ref can then be passed to a ref attribute on a jsx element and in that way we sort of create a reference to that specific element this ref that we are creating is actually an object and it has one single property called current that means that in order to work with this ref to manipulate the value of it or to use inbuilt browser apis on it we need to always access this current property the second tool here is the react use effect hook we use the use effect hook to run some code when the component first renders the code that will run inside of this use effect Hook is the javascript. focus method we will chain this Focus method on the rev. current that we're creating in the first step finally We'll add a tab index attribute to the same jsx element where we're also adding the ref attribute this ensures that the element is actually focusable by default all interactive HTML or GSX elements such as buttons or links or input fields or text areas are focusable that means that we get keyboard navigation and accessibility advantages right out of the box when we use interactive elements non interactive elements on the other hand are not focusable those are elements such as sections divs headings P tags and so on as soon as we set a valid value on the Tap index attribute the element becomes focusable in our specific case we'll set the value to be minus one because this makes the focusable element non tappable the term tapable refers to that a user can use their T key to reach this element when a focusable element is non- tappable that means that you cannot use your tab key to navigate your way to this element but you can still programmatically add Focus to it using the focus method this is quite a mouthful I know that so to give you a fair chance to digest all of this and actually understand how it works I have of course created another one of my pretty simple and very boring apps I am sure that this setup looks familiar to you but there's more than meets the eye take a look at what happens when I click the button wow not only did the question mark turn into a monkey face on the clicked button we also have these two cards up here a above the monkey face button the card to the left reads Focus you found the monkey while the card to the right reads you found the monkey secretly right now there is actually no difference whatsoever between these two cards apart from the text content but we are going to change that and add Focus to the card to the left when the two carts render so that you can see the difference between a focused and a nonfocused card in our index. jsx file we have an app component and a card component the app component renders this monkey face/ question mark button and as you've seen before clicking this button calls the handle click function which then updates both the content and the area label of the button so far so good this is all familiar code to what also happen happens when this function runs is that the is monkey found State variable which is declared up here is toggled right here using the set function is monkey found is initialized to false which makes sense because when our app first renders the content on the button is a question mark and there really is no monkey found there flipping this bullion value from false to True triggers the rendering of the card component the cards are rendered only when is monkey found is true as you can see the C component is right now super basic it simply returns a section containing two divs each rendering a ptag now our job is to add Focus to this div here when the card component renders as you now know we need four different tools to make this happen we need the use ra hook we need the use effect hook we need the focus method and we need the tab index attribute let's start by importing USF and use effect from react we do that up here right after the import of use State and now the hooks are available for us to use inside of our component now the first thing we'll do is that we'll create a ref using the use ref hook we do that with a const and I'm going to call this ref card ref we set this ref equal to use ref and we'll set the initial value here to be null now that we have a card ref declared we can pass that as the value of a ref attribute on the div that we want to focus so right here on the first of these two diffs we say ref and then between the curly braces here we pass in the carre this gives us a reference to this diff that we can now work with inside of a use effect hook we want to access the C ref and this cart ref is an object with one property called current on this cart ra. current we can now change the dot Focus method this code ensures that a as soon as our cut component renders the use effect will run only once the code inside of it will add Focus to our div finally we have to also actually make this div focusable right now it is not because a div is not an interactive element so we go down here to the div and after the ref attribute we add a tab index attribute on this tab index attribute we set the value minus1 with all of this new code our div here will now be focused as soon as we click the question mark button and it turns into a monkey face I have written some Focus styling inside of our CSS file that will now apply to this div but unfortunately this styling is not picked up in my recording so I would like to ask you to now on your own pause the scrim and run the code click the button to see the difference between the focus div and the not focus St please go ahead and do that now all right now I will run the code as well and walk you through the result of our refracturing here as soon as I click this question mark button the focus is now on this div here the background has changed to White the text color is dark and there's a bu Shadow on it hopefully you saw the same thing when you ran the code there is one last thing that I want to make completely clear here The Styling that I have added is just for you to be able to see that we are focusing this element it is not important when we use Focus as an accessibility tool since the whole purpose of this focus is to guide assist of Technology as to what it should read aloud to the users who cannot see the screen so you don't have to add any special Focus styling in order for this to work you have learned a ton of new things in this GM and in the next Rim we'll return to our memory game so that you get a chance to practice this by implementing it to our game over component see you there okay it is now time for you to put everything that you've just learned into practice I hope that you're ready cuz we are going to jump straight into your next coding challenge I want you to use the use rev hook the use effect hook the do Focus method and the Tap index attribute to add Focus to this Dev as soon as the game over component renders I then want you to actually play a memory game to check that your code is working I also have an important warning for you here you have to use keyboard navigation to see your browser's default Focus styling on the div I did not write any CSS this time that adds specific Focus styling so all you'll see is the default styling in Chrome that is a blue outline around the focused element but and this is the important part this blue outline in your Chrome browser or whatever browser you're using is only visible when you navigate using your keyboard if you use your mouse to click the very last memory card turn it and make the game over component appear you won't see any Focus stying so please use your keyboard now go ahead and pause the scram work on this Challenge and I'll be back with you in just a second to show you my solution all right I hope that went well let's do this together we need the use ref and user F hooks from react so the first thing we have to do is of course to import these hooks we do that up here at the very top of the file by saying import then curly braces because these are named Imports and then we import our hooks from react inside of our component we can now create a new const I'm going to call this one divre if you choose a different name for this variable that's completely fine we set our diff r equal to use ref with the initial value of null now that we have this diff ref we can add it down here on the div as the value of a riff attribute next we'll create a new use effect it has an empty dependencies array because we only want this code to run once when the component first Nots inside the use effect we want to add Focus to our ref here and we do that by saying div ref do current to access the current property on our ref and then chain the focus method onto it finally we want to add a tab Index right here on the div after the ref so we say tab index and give it the value minus one and that should be it now it's time to run the code and check that everything is working I am just going to speed through this game so you don't have to watch me do it in real time okay we now have one cut left to turn as you can see my mouse is up here and I'm going to use my keyboard as I've done all the way through to turn the last card so I hit enter and on my screen I can see a blue outline on the div I know that you cannot see this one it is not picked up in the recording but hopefully you saw it when you played the game on your own what you will be able to to see though is that when I now hit my Tab Key just once the focus is now on the play again button and this is a sign that the focus moved one level down from the div to the button if you managed to take in all of this new information and implement it into our memory game you should be very proud of yourself this is a super important accessibility Improvement that we just made here our next big task was will be to work on the Arrow handling in our game so when you're ready to tackle that I'll see you in the next scrim in the very beginning of this course we worked on the start game function that makes a call to the Emoji Hub API to fetch the Emojis data that we are rendering on our memory cards in this function we use the try catch syntax to catch potential errors here in the tri block we check if the response is okay and if not we throw a new error which is then card down here in the catch block and console locked this is all very good because we are preventing our app from just crashing if the data fetching fails but so far we are only logging an error message to the console meaning our users don't get any information about what is going on to illust just how bad the user experience is right now let's throw a new error inside the tri block up here at the very top of the block before we do anything else we simply say Throw new error with the same syntax as we're using right here so we can copy paste this line of code paste it in here and I'm just going to change the error message we are throwing an error let's run this new code to see what happens we click the start game button we get an error message in the console and that is the error message that we just created here when we threw the error but in the UI nothing happens the user doesn't even know that there is an error to them it might just seem like we wrote a crappy app that simply doesn't work that is of course not good enough what we want to do instead is to create a new component displaying an error message and we'll render this component in case any goes wrong when we try to fetch data from the API I have taken some screenshots here so that I can show you what we are aiming at as you might remember this is what the form component looks like in our finished memory game so just a little teaser we'll be building that one soon but the important part now is that if we click the start game button and something goes wrong when we're trying to fetch data this is what will happen in the UI will render a component saying sorry there wasn't error and will'll even give the user an opportunity to click a restart game button to take them back to the form where they can try again and see if things work now to achieve all of this there are several things that we need to do we need to create this new component of course and we also need to write some code here inside of the app component so that we can control when to display our new error component in the next scrim we'll focus on the letter and write all the code necessary for our yet Tobe created error component to render correctly see you there in order for us to be able to render an arrow component in case the data fetching fails we need to save some information instead that tells us if there is an error or not when our memory game first renders what we see in the UI is the form component at this stage we haven't yet made an attempt to fetch any data so we can safely assume that there is no error either as soon as we hit the start game button this code here inside of our start game function runs we'll then either get some Emoji data back that we can work with or we'll get an error in case of an error the code inside of our catch blog is what will be executed and here we want to update the error information that we're saving in state to say that yes now we do have an error when that happens we want to to render this Arrow component that I also showed you in the previous scrim this component has a restart game button on it and in this case restarting implies that we again update the error information in state to say no we no longer have an error and that we send the user back to the form component so this is the logic that we have to build into our app and surprise surprise now it is time for you to turn all of this into code in step one of this challenge I want you to create a new state variable called is error with a corresponding set of function and initialize it to false in step two I want you to go inside of the catch Block in the start game function and set is eror to true in step three I want you to create a new function at the bottom of this file you should call this function reset error and what it should do is that it should set this error back to false in step four you should go inside of the tri Block in the start game function and throw a new error with a custom error message and you should also log is error to the console finally in step five I want you to run the code to check that everything is working as expected because this involves writing code in various different places in the same file I have given you a bit of help as you can see I've written comments saying where each step is to be solved so step one code code here step four code below here and so on so you can see we have step four here in the tri block step two here in the catch block and finally step three down here above the return statement I do also have a little warning here we won't be able to test the reset eror function at this stage since we're not yet calling it so don't worry about that bit for now what I want you to test is that you are successfully flipping the is error State variable to true when you throw an error inside of the tri block okay pause the scrim now jump into the code and solve this Challenge and return back to me to see my solution all right I hope that went well let's do this together we'll start by initializing some new state here as always we do this using a const we open up the square brackets and we call the variable is error and then we create the set of function set is error this should be equal to use State initialize to false that was part one of the challenge done step two is to go into the catch blog right here and flip our new state variable from false to true so we run the setup function set is error and set the value to true that was step two done in in step three we should create this new reset error function all the way down here at the bottom of the file we create a new function called reset error and in here we run the set is error function again this time setting State back to false and that was step three done in step four we are to throw a new error inside of the tri block right here so we say Throw new error and pass in a custom error message I am now throwing a brand new error that's going to be my custom error message we also want to log is error to the console up here so we say console log is error and that was step four all we have left now is to run the code and check that everything is working as expected so we can safely delete the last part of our challenge text here let's run the code down in the console we saw the word false in fact let's just open up the console so we can actually see what's going on here we get false lock to the console because is error is initialized to false now when we click our start game button then we should immediately get an error because we are manually throwing an error inside of the tri block and in the console we see the custom error message I am now throwing a brand new error and we see that this error is flipped to true excellent we now have all the logic set up that we need in order to render an error message to our user if something goes wrong with the data fetching in the next scrim we will build this component and render it to the UI so when you feel ready to tackle that one I'll see you in the next scrim okay I hope that you're ready to flex your coding skills because I'm about to give you your biggest challenge so far in the course you already know what we are aiming for an arrow component that is rendered if the data fetching fails with a button on it that we can click to reset the error and go back to the form so without further Ado let's just get going here it is your mega challenge read through each step carefully I have described everything you have to do and giving you a hint as well it is a mega Challenge and I understand understand if you feel a bit overwhelmed right now but trust me if you've been following along and have soled the previous challenges then you've got what it takes to solve this one too one last thing before I leave you to it be aware that we are still throwing an error right here inside the tri block of our start game function we need this error to render the new eror card component that I'm asking you to create but just in case you want to try out other things along the way and actually start a memory game make sure to comment out this line of code all right pause the scrim now give this your very best chart remember to check out the hint if you ever get stuck and return back to me to see my solution so I hope that went well let's do this together step by step we'll start out by creating the new file for our aroc cart component as you very well know by now you won't be able to see what I'm doing on my screen so I'll just speed up and get this file ready for us inside of this aroc card. jsx file we set up the basic Syntax for our new component we make a default export here as we've done so many times before and inside of the component we want a return statement we know that we want to return a div wrapping around two P tags and an instance of the regular button component it in order for us to actually render this regular button we need to import it as well at the top of the file now that we have our elements in place we can go back to the app and simply do some copy pasting to get the content in here as well everything is written out for us already here in step one so once again I'm just going to speed up and do some copy pasting now that we have all our content pasted in here I believe we are done with step one so let's go back and look at the next step in the challenge in step two our job is to style the elements in this new component once again I'll speed up and do some copy pasting of our strings here so that you don't have to watch me do everything in real time so we now have class names on our div and on our two PX and we are done with step two in step three the only instruction I gave you was to make our Arrow card accessible hopefully you figured out that what you have to do here is exactly the same as what we did in the game over component inside of our Arrow card we need to start out by importing the use ref and use effect hooks from react then inside of the component we create a new const called div ref and set it equal to use ref and initialize it to n then we add this new div ref to a ref attribute onad right here after the class name next we create a use effect with an empty dependencies array because we want it to only run once when the component first renders in here we take the div rev and we access its current property and on this one we chain the focus method finally we add a tab index with the value of minus one to our dip now our Arrow card is accessible in the exact same way as our game over component let's go back to the challenge again to see what we have to do next now it is time for us to actually render this Arrow card so we of course need to import it first before we can do anything else we do that up here at the top of the file together with all our other Imports then we scroll down to the very bottom of the file and we render this eror card component below the memory card whenever is error is true so all we have to do here is say is error and then use the logical and operator and render an instance of error cut that was step four of the challenge done in step five we are to pass the reset Arrow function through props to the regular button in the arrow card and use it on the onclick event handler in the regular button component so once again we'll scroll down to where we're rendering the arrow card then we pass a prop here called handle click with the value reset error inside of our Arrow card we want to receive this prop and then pass it one level further to the regular button inside of the regular button we are already receiving this handle click prop up here and using it down here on the unclick event handler so that was it for this step of our challenge I can no longer remember the number of it but it was step five in Step six we have to refactor the conditional rendering of the form component so that it is not rendered when there is an error so down here inside of the return statement we want to add an extra conditional check here the form should render when the game is not on and when there is no error so we use the exclamation mark and is error and of course the logical an operator that was it for step six the only thing we have left to do now is to run the code and check that it is working so let's delete this last part of the challenge and then just cross our fingers and hope that we didn't miss anything here when we click the start game button now what we should see is our new Arrow component and we do the component is rendered just as we wanted to and the form is gone now when we click the restart game button we should be taken back to the form let's hope that this part works as well and it does amazing this was a huge Challenge and I want to say here that no matter if you manage to solve all of it or parts of it or none of it you should be proud of yourself for even trying everything that I asked you to do here was something that we have done elsewhere in the code but that does not make a challenge easy so give yourself a huge pad on the back be proud of all the hardwork you put into this and remember to take a break whenever you feel like you need it when you're feeling refreshed move on to the next Grim where we will take the first steps towards making our form component an actual form see you there throughout the entire course we have lived with this rather poor excuse of a form that contains nothing but a button as you probably remember our finished form should also contain two select menus that allow the user to select an emoji category and a number of memory cards in order to make this change there are two things that we have to do we have to of course build the actual form elements and we also need to do some refactoring here in our app component so that we can use the data that we get from the form instead of hardcoded values when we fetch Emoji data and render memory Cuts we do have quite a lot of work to do here so we'll break it down into multiple scrims and take it step by step the first thing we'll focus on is to refactor the relevant parts of our app component right now we have hardcoded values in two places here in the URL that we use to make the fetch request to the Emoji Hub API as you can see the last bed of the string here is the hardcoded Emoji category animals and nature we are also hardcoding a value down here inside this followup namely the number five it's been a very long time since we wrote this function here so I'm just going to quickly remind you of what it is we are actually doing in the follow here we are generating random numbers here on line 65 and then we push them to the random indices array here inside of the if statement finally we are returning that array down here and we're using this return value up here in the git data slice function in this function we are using the do reduce method to iterate over the array of random numbers returned from the get random indices function and then we use each of these random numbers here as an index to get a random element from the data that we are receiving as a parameter all in all this creates a new array called Data slice which we then returning from the get data slice function right here so the essence the import thing here is that the length of this random indices array is what determines the number of memory cards in our game we have hardcoded the number five in the for Loop which gives us five random unique emojis and in the end five emoji pairs meaning 10 memory cards because we're duplicating each Emoji okay so now we have sort of an overview of where we need to refactor our code and I think that you are ready for a new challenge in step one I want you to go up here to the very top of the component before the state variables and create a new variable called initial form data you should set this variable equal to an object with the key value pants that I have written out right here in step two I want you to create a new state variable called fun data with a corresponding set of function and give it the initial form data that you just created as the initial value in step three I want you to update the URL in the fet request to use the category saved in form data instead of the hardcoded category and in step four I want you to update the for Loop and the get random indices function to use the number saved in form data instead of the hardcoded number five finally in step five I want you to run the code and start a game to check that your refracted code is working you should still get exactly 10 memory cards rendered to the mini browser and in case you're struggling to figure out how to do that then take a look at the hint that I have written out for you down here so pause the scri now jump into the code and try to solve this Challenge and I'll be back with you in just a second to show you my solution all right hopefully you managed to do that just fine let's go through this together now we'll start by creating the new variable initial form data up here as the very first thing we do inside of the app component we do that using a const and then the name of our variable initial form data and we set this equal to an object so we need our curly braces inside of the object we want two key value paths the first one should be category and this one should have the value animals and nature as I've written out right here so I'm just going to copy paste this one the second key should be called number and have the value 10 and that was step one done in step two we are to create a new state variable I'm going to do that right here above the rest of our state variables so we say const open up the square brackets and then we say form data and create the set function set form data this should be equal to use stage with initial form data as the initial value now we're done with step two in step three we are to change the url here to no longer have the hardcoded category animals and nature and instead use the category that we just saved in the form data so the first thing we need to do here is of course to change this from a string to a template literal then we delete the hardcoded category and we use the dollar sign and cly bases to add in the category that we have saved in our form data that was it for step three in step four we'll have to go down to the get random enes function and change this hardcoded number five to the number that we have saved in form data though if we simply say form data. number we won't get 10 memory cards r it to the mini browser we'll get 20 memory cards because remember down here in the get emojis array we are duplicating each Emoji in the data so that we get emoji pairs therefore we need to ensure that we get half as many unique emojis as the number of memory cards that we want to render it might sound more complicated than it actually is because all we have to do is to divide form data. number with two I don't think that the parenthesis that I set here around this mathematical operation is actually necessary but I like to have it here because I think it improves the reability of our full loop finally all we have left to do now is to run the code and check that everything is still working so we start a new game and hopefully we will see 10 memory cards just this before and they will still come from the category animals in nature we definitely have 10 cards and these leaves here definitely look like something that comes from animals in nature great we have now set the stage for the rest of the work we need to do here our app is ready to consume the form data and in the next Rim we'll start building the actual form elements see you there in this scrim we'll create two select elements right here inside of our form component one for the Emoji category and one for the number of memory cards for now we will hard code these formuls because I think it's a lot easier to understand how to work with forms in react when we have everything in one place and can really see that the select menus and their options are in fact one coherent form unit so to speak before I give you the scrims challenge there are a couple of small changes that we need to make to this component for styling purposes we need to wrap the entire form in a div and this div should have the class name form container we also need two new divs inside of the form element that will be wrapping around one select element each on these two divs we have the class name form in a wrapper and again this is M for styling purposes so with these new divs in place I believe that you are ready for your next challenge here is what I want you to do in Step One create two new select elements one for the Emoji category and one for the number of memory counts each select menu should have a name an ID and an unchange event handler and I have of course written out the values that I want you to use on this name ID and unchange right here as part of Step One in step two you should create five option elements inside of each select element using the values that I have written out right here as part of step two in step three give each select element a label describing the select menu this was the first half of the challenge and inside of the app component there are two more steps in here I want you to create a new function called handle form change this function should receive the event as a parameter inside of the function I want you to then use the event to get the name and the value of the selected option and for now simply lck name and value to the console finally in step five you should pass this handle form change function as the prop handle change to the form component and remember to also receive this prop inside of the form we do of course also need to test this no code I realize now that I did not write that as part of the challenge so give me a second while I fix that here it is Step six run the code and select some options in the form to test that your code is actually working let's go back to the form where you will start with all of this artw work if you feel a bit Rusty on how to create select menus Google is your friend there are loads of resources out there so please do use those if you get stuck pause the scam now give this your best chat and I'll be back with you in just a second to show you my solution all right I hope that went well let's get to work we'll start right here inside of the first Dev by creating the select element for our Emoji category first of all we need the actual select tag on this select tag we need a name and an ID both with the value category and we need an unchange event handler with the value handle change the select element for the number selection should look very similar to this one so I am now going to Simply copy this one paste it in down here in the div delete this comment that we don't need anymore and change the value category to number that was it for step one in step two we want five options inside of each select element again we'll start up here with the category we create an option and on this very first option we want the value animals and nature we also need to write something here between the opening and closing option tag and that is what will actually be rendered when we open up the select menu so here we simply write animals and nature again but in a more human friendly way without the hyphens between the words and now I'm simply going to speed up and fix the four remaining options here in our first select element here we have our five options animals and nature food and drink traveling places objects and symbols let's do the same thing down here create five option elements passing in the correct values once again I'll speed type so you don't have to see me do it in real time here we have them options with the values 10 20 30 40 and 50 and that was step two done here finally we are to set a label on each element describing what it is we are selecting so we use the label tag here and on this first one I'll say select an emoji category now in order for this label to actually be connected to the select menu below we need to use the HTML 4 attribute and give this the same value as we said on the ID of the select element and once again we do the same thing down here on this label I think we should say select the number of memory cards and once again we'll give it an HTML 4 attribute with the same value as the one we set on the ID of the select element that should be it for the challenge here inside of the form component in the app component we'll now create this new function called handle form change this function should receive the event and now that we are receiving this event we can use it to access the name and value of the selected option we do that by saying e. target. name and e. target. value then the name that we will get here is the name that we are setting on our select elements so category on the first one and number on the second one the values that we are getting with e. target. value come from the option elements so this one for instance the second option in the category select element has the value of food and drink so if we click the select option here we'll get the name category and the value food and drink back in our component our task was to lock these two to the console I will create a template literal here so that I can create one single console log with the name first then a colon followed by the value that was it for step four and step five we should pass this new function as the prop handle changed to the form component we do that right here where we are rendering an instance of form so we say handle change and give it the value handle form change with this extra prop added our formatting is getting a bit crazy here so let's just clean that up nice this is a lot more readable the only thing we have left to do now is to receive this prop inside of the form component up here in the function declaration we can simply add handle change right here after the handle submit prop okay now it's time to test our new code and see how it works we run the code and here we have a form excellent I will now click the first select menu here to select an emoji category I know that you are not able to see the displayed options in the recording but hopefully you did this on your own and tested the code so that you know what it looks like I'm now clicking the option food and drink and down in the console we can see that that is exactly what we are logging categ food and drink let me just select a number of memory cards as well I'll go with 40 and in the console we can now see number colon 40 logged out so our select menus including labels and options are rendered correctly inside of the form component and our handle form change function is also hooked up correctly with the form and tracking the selected options we do of course need to do something more than just logging the name and value to the console here inside of the handle form change function since we want the users Selections in the form to actually be saved in our form data in State this is exactly what we'll be tackling in the next Grim so when you feel ready to move on I'll see you there a few scrims ago we created this form data State variable and we gave it the initial value of initial form data that is is the object that we created up here containing the two keys category and number and their corresponding values in this scrim our job is to update the code down here in our handle form change function to use the setter function from the form data State variable to replace the initial value of form data with the actual selections made by the user in our form the handle form change function here is handling changes in both of the select elements in the same way as the form data state rable is to keep track of and manage these Selections in both elements this implies that we cannot hardcode anything related to the form data in this function because we simply don't know in advance which select element the user is interacting with when the unchanged event handler on a select element is triggering the function instead we have to rely 100% on the information that we can retrieve from the event that we are receiving as a parameter let's run the code that we have right now and select some options so that we can inspect what it is we are logging to the console and how we can use it to update our formam data I will now select food and drink as the category and 20 as as the number of memory cards as you can see this e. target. name is clearly category in the first select menu and number in the second these two values are the exact same as the ones we are using up here on the initial form data object this tells us one important thing and that is that when we want to update the form data in state we can use e. time target. name as a key in the form data object and as I'm sure you've already figured out we can then use e. target. value as the value set on this key now that we have outlined a strategy here it is time for your next challenge when the handle form change function runs you should update form data to store the most recent selections made in the form form data should always be an object with two key value pairs you should use e. target. name as the key and e. target. Val as the value I do have a hint for you as well remember to keep track of the previous state and the object spread operator can help you with this pause the scrim now jump into the code and solve this Challenge and return to me to see my solution okay I hope that went well let's do this together I'll start by simply deleting this console lock because we don't need it anymore now we can run the set form data set function and in here we need a call back function so that we can keep track of the previous state I'm going to go with preform data as the name of our parameter Here and Now inside this callback function we want to return a new object though we cannot not just write curly braces like this and then start creating our object cuz as soon as we add curly braces after the arrow in an arrow function JavaScript perceives this as the opening of a function body therefore we need to wrap our object here in a set of normal brackets if we want to be able to write our object without actually opening the function body and using the return keyword we know that we have to keep track of the previous state and the reason we have to do this is actually quite obvious the user can only ever make a selection in one select menu at a time meaning we have to keep track of what was most recently selected in the other select menu the one that we are not dealing with currently we can do this using the object spread operator with these three dots and then spread in the preform data now we want to use e. target. name as the key in this updated object but as you can see JavaScript is not happy with us right now there's clearly something wrong with the way that we are trying to use this e. targetname as the key the problem is that we cannot just use a property on the e. Target object as the key as we're doing right here without wrapping this in square brackets but if we do that the red squiggly lines are gone and instead it has moved out here to the closing curly bracket and that is simply because we have not yet declared a value on this key so let's do that now e. target. value and this should be it for this challenge when we run this code now and make some Selections in our form we should see that we are able to customize our memory game let's give it a shot I am going to go with food and drink and I want 30 memory cards I think so now when I start the game hopefully we'll get 30 memory cards and on these cards we will see food and drink emojis okay we definitely have a lot of cards I believe there are exactly 30 here let's turn the first one and this is a cucumber let's turn a few more to see what this food and drink caty has to offer some sort of cookie a shrimp I think and a beer well cheers what a wonderful coincidence that we found a beer now that our form is working the only thing we have left to do now in this course is to refactor our newly created form to use reusable components as the form elements instead of all the hardcoded elements that we have right now when you are ready for this big refactoring I will see you in the next scrim you remember this data.js file it's been lying right here throughout the entire course in our data folder waiting for us to reach the point that we're at now where we are to refactor the select element in our form from hardcoded jsx to reusable react components before I say anything more I would like you to take a good look add this data on your own pause the scrim now take a second to familiarize yourself with the code and return to me when you're done okay as I'm sure you can see the data that we have here corresponds with the information that we attached to the select elements in our form and therefore also to the form data that we are saving and state the data variable itself is an object with two key value Pairs and on each of these Keys the value is an array of objects now that we want to replace the hardcoded select elements with reusable components this is the data that we'll use to create those components inside our form component our goal is to get rid of these two dips here inside of which we are currently rendering our select elements and instead that render one single instance of a new select component just to get us started I have actually already created a file for this new component right here in the components folder though as you can see there's not much going on in here right now on line one we are importing the data object that we just looked at and then we are exporting a functional component called select that receives a prop called handle change back in the form component we are importing the select right here but currently we are not rendering it in the challenge that I'm about to give you I want to allow you to focus only on the r
Original Description
Create an accessible, interactive memory game using React. This course takes you through building a polished project while exploring how to fetch data, manage state, and implement best practices for inclusivity and functionality.
✏️ Study this course interactively on Scrimba:
https://scrimba.com/memory-game-in-react-c0a3odsk39?utm_source=youtube&utm_medium=video&utm_campaign=fcc-memory-game-launch
Code is available on the Scrimba course page for each lesson.
Discover how to build a fully interactive memory game in React, designed to enhance your development skills and with a focus on accessibility.
This course guides you through each step, from fetching and managing API data to designing reusable components and implementing user interactions.
You’ll work on challenges such as randomizing game elements, detecting matches, and handling errors. Along the way, you'll gain practical experience in solving common development problems.
Accessibility is a key focus of the project, with detailed guidance on ARIA attributes, semantic HTML, and designing for inclusivity.
This course is ideal for anyone looking to deepen their React knowledge while working on a meaningful, real-world project. By the end, you’ll have an accessible, polished memory game that demonstrates your skills and commitment to building user-friendly applications.
Scrimba on YouTube: https://www.youtube.com/c/Scrimba
Timestamps:
Building the Foundation
0:00:00 - Intro
0:06:00 - Boilerplate code
0:11:53 - Fetch data from API
0:17:18 - Store API data in state
0:21:19 - Aside: HTML entities
0:26:08 - Render memory cards with API data
0:30:45 - Issue with emojisData
0:33:29 - Get random emojis pt. 1
0:43:32 - Get random emojis pt. 2
0:49:32 - Duplicate and shuffle emojis
Core Game Functionality
0:55:10 - Side note: Address future discrepancies
0:58:59 - Select a memory card pt. 1
1:05:22 - Select a memory card pt. 2
1:10:37 - Select a memory card pt. 3
1:20:16 - Detect matching cards
1:28
Watch on YouTube ↗
(saves to browser)
Sign in to unlock AI tutor explanation · ⚡30
Playlist
Uploads from freeCodeCamp.org · freeCodeCamp.org · 0 of 60
← Previous
Next →
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
React: Production Server Setup Part 2 - Live Coding with Jesse
freeCodeCamp.org
cookies vs localStorage vs sessionStorage - Beau teaches JavaScript
freeCodeCamp.org
Browser history tutorial - Beau teaches JavaScript
freeCodeCamp.org
Graph Data Structure Intro (inc. adjacency list, adjacency matrix, incidence matrix)
freeCodeCamp.org
React: Parameterized Routing with Next.js - Live Coding with Jesse
freeCodeCamp.org
React: Dealing with jQuery Issues - Live Coding with Jesse
freeCodeCamp.org
setInterval and setTimeout: timing events - Beau teaches JavaScript
freeCodeCamp.org
Browser and Device Testing - Live Coding with Jesse
freeCodeCamp.org
Last Minute Updates - Live Coding with Jesse
freeCodeCamp.org
Post Launch Updates - Live Coding with Jesse
freeCodeCamp.org
React: Setting Up Google Analytics - Live Coding with Jesse
freeCodeCamp.org
React: Masonry Layout - Live Coding with Jesse
freeCodeCamp.org
Load Balancing Digital Ocean Droplets - Live Coding with Jesse
freeCodeCamp.org
try, catch, finally, throw - error handling in JavaScript
freeCodeCamp.org
Load Balancing: SSL Passthrough Setup - Live Coding with Jesse
freeCodeCamp.org
Graphs: breadth-first search - Beau teaches JavaScript
freeCodeCamp.org
React: Masonry Layout Part 2 - Live Coding with Jesse
freeCodeCamp.org
React: WordPress API Live Search - Live Coding with Jesse
freeCodeCamp.org
Creating WordPress Custom Post Types - Live Coding With Jesse
freeCodeCamp.org
Dates - Beau teaches JavaScript
freeCodeCamp.org
Miscellaneous Front End Updates - Live Coding with Jesse
freeCodeCamp.org
Merging a Pull Request from GitHub - Live Coding with Jesse
freeCodeCamp.org
React + Prettier + Standard JS - Live Coding with Jesse
freeCodeCamp.org
React: Sortable Responsive Table - Live Coding with Jesse
freeCodeCamp.org
Geolocation Sorting by Distance - Live Coding with Jesse
freeCodeCamp.org
Tradeoff Matrix - Agile Software Development
freeCodeCamp.org
The Definition of Ready - Agile Software Development
freeCodeCamp.org
Getting first React job without experience - Ask Preethi
freeCodeCamp.org
React: Google Analytics Click Tracking - Live Coding with Jesse
freeCodeCamp.org
Submitting a PR to an Open Source Project - Live Coding with Jesse
freeCodeCamp.org
Should I go back to school to get CS degree? - Ask Preethi
freeCodeCamp.org
Hero Section CSS Changes - Live Coding with Jesse
freeCodeCamp.org
Working Agreement - Agile Software Development
freeCodeCamp.org
A day at Pennybox with Co-Founder Reji Eapen
freeCodeCamp.org
React: Sorting and Filtering Data - Live Coding with Jesse
freeCodeCamp.org
React: Sorting and Filtering Data Part 2 - Live Coding with Jesse
freeCodeCamp.org
React: Building a New UI - Live Coding with Jesse
freeCodeCamp.org
Definition of Done - Agile Software Development
freeCodeCamp.org
Getting started with jQuery (tutorial) - Beau teaches JavaScript
freeCodeCamp.org
Making a React Blog with WordPress Content - Live Coding with Jesse
freeCodeCamp.org
React, NextJS, CSS - Live Coding with Jesse
freeCodeCamp.org
jQuery events - Beau teaches JavaScript
freeCodeCamp.org
React/NextJS Routing and WordPress API Custom Types - Live Coding with Jesse
freeCodeCamp.org
React: Working with API Data - Live Coding with Jesse
freeCodeCamp.org
React: Refactoring Components - Live Streaming with Jesse
freeCodeCamp.org
jQuery effects - Beau teaches JavaScript
freeCodeCamp.org
More React Refactoring - Live Coding with Jesse
freeCodeCamp.org
animate in jQuery - Beau teaches JavaScript
freeCodeCamp.org
"Finishing" My React Site - Live Coding with Jesse
freeCodeCamp.org
Starting a New React Project (P2D1) - Live Coding with Jesse
freeCodeCamp.org
React Project 2 Day 2: Learning Material UI - Live Coding with Jesse
freeCodeCamp.org
The Agile Manifesto - Agile Software Development
freeCodeCamp.org
jQuery: get and set with http, text, val, and attr - Beau teaches JavaScript
freeCodeCamp.org
React Project 2 Day 3 - Live Coding with Jesse
freeCodeCamp.org
The INVEST approach to product backlog items
freeCodeCamp.org
React Project 2 Day 4 - Live Coding with Jesse
freeCodeCamp.org
Chickens and Pigs - Agile Software Development
freeCodeCamp.org
React Project 2 Day 5 - Live Coding with Jesse
freeCodeCamp.org
jQuery: add and remove DOM elements - Beau teaches JavaScript
freeCodeCamp.org
React Project 2 Day 6 - Live Coding with Jesse
freeCodeCamp.org
More on: React
View skill →Related Reads
📰
📰
📰
📰
How I made a scroll-scrubbed video portfolio fast (Next.js 15 + GSAP + canvas)
Dev.to · Pratham Sharma
5 Reasons HTML Is About to Change Frontend Development
Medium · Programming
5 Reasons HTML Is About to Change Frontend Development
Medium · JavaScript
copilot browser tools make the frontend reviewable
Dev.to · Paulo Victor Leite Lima Gomes
Chapters (15)
Intro
6:00
Boilerplate code
11:53
Fetch data from API
17:18
Store API data in state
21:19
Aside: HTML entities
26:08
Render memory cards with API data
30:45
Issue with emojisData
33:29
Get random emojis pt. 1
43:32
Get random emojis pt. 2
49:32
Duplicate and shuffle emojis
55:10
Side note: Address future discrepancies
58:59
Select a memory card pt. 1
1:05:22
Select a memory card pt. 2
1:10:37
Select a memory card pt. 3
1:20:16
Detect matching cards
🎓
Tutor Explanation
DeepCamp AI