Skip to main content

Build a Memory Game in React

Ajo Borgvold's Pro project course has you build one emoji memory game in React over about 4.4 hours, with a full module on making it work for screen reader and keyboard users. It is the project to pick over a generic React build if accessibility is the skill you came for.

Reviewed inside the course with a Pro account, September 2026: every module opened, transcripts read for 26 of the 43 scrims, including the intro, outro and each module's first lesson.

Quick answer​

This course fits developers who already know hooks and fetch calls and want reps grading themselves against specific briefs. The catch: it is one project, not a survey, so there is no routing, testing or TypeScript. Finish it and move to Advanced React, which covers what this build leaves out.

Title card of Scrimba's Build a Memory Game in React course: Build a Memory Game, With React and the EmojiHub API, Teacher: Ajo Borgvold
The course title card from the intro scrim. The four modules open straight into code, so this is the only chapter card.

Is it worth your time?​

If you have finished Learn React and want reps, this is a well built set of them. Two thirds of the scrims are challenges: Ajo pastes a numbered brief into the file, tells you to pause, and comes back with a solution you compare against your own. The briefs are specific (variable names, class names to copy, a hint and a warning), so you are never guessing what "done" looks like. And the solutions are typed live: Ajo's own answer to the first fetch challenge throws a ReferenceError from a typo before it works.

The accessibility module is why you would pick this course over another project build. Most project tutorials add an aria-label somewhere and call it done. This one spends 74 minutes on why a screen reader user gets an HTML entity code instead of an emoji, how aria-live="polite" decides when to speak, why matched cards should be disabled so the Tab key skips them, and how to move focus to a component that just appeared so it gets announced. If you have never thought about any of that, you will after this.

Two caveats. It is one project, not a survey: no routing, no Context, no testing, no TypeScript, and the CSS is written for you. And there is a seam Ajo owns up to in a "side note" scrim: three module 1 lessons were re-recorded after the rest, so the code you see from module 2 onward has unnecessary async keywords and a reduce where a map would do. Nothing breaks, but you should know why the code shifts.

What you'll learn​

Course curriculum

4 modules · 43 lessons

  1. Building the Foundation54 min10 lessons
  2. Core Game Functionality68 min10 lessons
  3. Accessibility Enhancements74 min13 lessons
  4. Advanced Features66 min10 lessons

Lesson counts are the scrims I counted in each expanded module in September 2026, including intros, asides, side notes, a "Want to become a Scrimbassador?" promo in module 3, and the outro. Scrimba's module headers show 8, 12, 10, and 8 (38 in total), while the course listing and its structured data say 44 lessons, which adds a standalone one-minute "How to Utilize Your Certificate" clip after the last module. When other pages on this site quote 44, that is Scrimba's number.

Inside the course, module by module​

1. Building the Foundation (54 min, 10 scrims)​

The intro shows the finished game (a form, face-down cards, a "play again" box) and sets expectations plainly: "when I say familiar with, I mean familiar with. You're not supposed to be an expert because if you were, you wouldn't need to take this course at all," as Ajo puts it at 3:52. Then "Boilerplate code" asks you to pause and read the starter files (App.jsx, Form.jsx, MemoryCard.jsx, RegularButton.jsx, a data.js you will not touch until module 4) and write comments to yourself before Ajo walks through them. The CSS is all pre-written: "your only job when it comes to styling is to use the class names that I tell you to use."

From there the challenges start and do not stop. "Fetch data from API" has you make startGame async, wrap a fetch to the EmojiHub API in try/catch, and throw on a bad response. "Store API data in state" slices the first five emojis into useState. An aside on HTML entities explains why an entity stored in a variable does not decode itself, and adds the html-entities package to fix it. Then the emojis render, and "Issue with emojisData" stops to plan in plain English: pick five random emojis, duplicate them, shuffle them.

Build a Memory Game in React, Fetch data from API lesson: code editor beside a console reference error.
Fetch data from API at 4:22. Ajo mistypes reponse on line 18 while narrating the solution, and the console throws ReferenceError before the fix a few seconds later.Screenshot of scrimba.com, taken by scrimbaguide.tech.

The two "Get random emojis" scrims open with "mini challenges" (think, no typing: how do you get random indices, how do you keep them in range?) before a for loop that pushes five random indices. "Duplicate and shuffle emojis" closes the module with the Fisher-Yates shuffle, which Ajo tells you to Google: "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 either." By 5:14 there are ten shuffled cards in the preview.

Build a Memory Game in React, Duplicate and shuffle emojis lesson: preview showing ten face-up emoji cards.
End of module 1 at 5:22: ten cards, five pairs, shuffled. They still show their emoji; the face-down question marks come in module 2.Screenshot of scrimba.com, taken by scrimbaguide.tech.

2. Core Game Functionality (68 min, 10 scrims)​

It opens with the "side note" about re-recorded lessons ("recordings show no mercy, as you know"), then three "Select a memory card" scrims build the turnCard logic step by step. Part 1's mini challenge asks what identifies a clicked card (its index) and a pair (its name), and why the name beats the HTML code "as a service to our fellow developers." Part 3 has you write the rules as pseudocode first: a card can be in the selection once, and there can be at most two selected. Ajo tests it on screen: click a snail, click it again (nothing), click the other snail (two objects), click a tree (selection resets).

"Detect matching cards" is where useEffect arrives, with a mini challenge asking which React tool should check for matches whenever two cards are selected, and a clear explanation of the dependency array. "Create EmojiButton component" ("This was a huge challenge") pulls the button into its own component, and the two "Conditional" scrims give each card its content and its classes based on whether it is selected, matched, or neither. Ajo uses chained ternaries and says a let with if/else is fine too.

Build a Memory Game in React, Conditional memory card styling lesson: preview showing a greyed-out matched card pair.
The not-allowed cursor, at 8:42 of the Conditional lesson, comes from a chained ternary that swaps classes once a pair is matched, the technique Ajo says a plain if/else could replace just as well.Screenshot of scrimba.com, taken by scrimbaguide.tech.

3. Accessibility Enhancements (74 min, 13 scrims)​

Slide from Scrimba's Build a Memory Game in React course: aria-label and aria-live make elements accessible to screen readers.
This aside explains aria-label and aria-live, and why each card needs a label instead of relying on its HTML entity code for its accessible name.
Slide from the focus aside in Scrimba's Build a Memory Game in React: Accessibility tool: Add focus to new DOM element
This 10:26 aside covers useRef, useEffect, .focus(), and tabIndex, the four tools that move focus to a new element so a screen reader announces it.Slides from scrimba.com.

The module opens with a slide-based aside on aria-label and aria-live. Ajo reads the MDN definition, then answers when to use a label: "The short answer is when we have no other option." The memory game is that case: each button's accessible name is an HTML entity, so a screen reader reads a code instead of "monkey face." The aside ends with a detail I had not seen taught elsewhere: end every aria-label string with a period so the screen reader pauses.

Back in the game, "Disabled attribute & conditional event handler" shows that the greyed-out matched cards still log "clicked," adds disabled, and demonstrates the Tab key skipping them. "Add aria-label to EmojiButton" refactors the button to receive the whole emoji object and labels each card "Position 3:" followed by the emoji's name and a period (index plus one, because "humans tend to start counting from one"). "Create AssistiveTechInfo component" adds a visually hidden section announcing matched pairs and cards left, and walks through the sr-only CSS: "If you want to hide something, like really hide it so that nobody will ever find it, then go ahead and use display none or visibility hidden."

The last third builds the GameOver component and then fixes the problem it creates. A new element is not announced when it appears, so the "Focus as an accessibility tool" aside introduces what Ajo calls "a cocktail of tools": useRef, useEffect, .focus(), and tabIndex="-1". "Make GameOver component accessible" has you apply all four, with the warning that Chrome's focus outline only shows if you navigate by keyboard.

4. Advanced Features (66 min, 10 scrims)​

Error handling first: an isError state flipped in the catch block, a resetError function, and an ErrorCard component with a restart button. Then the form. "Create form elements" has you hardcode two select menus (emoji category, number of cards) with labels and an onChange that logs name and value; "Save form selections in state" stores them. The two "Refactor form" scrims finally use data.js: Object.entries(data).map(...) builds a reusable Select component, then an Option component. Ajo calls part 1 "not an easy challenge" for the destructuring and chaining involved.

The final challenge closes the accessibility loop. The form reappears after game over or an error, and is not announced. Focus must move to it, but only on re-render, or the "Memory" heading would be skipped on first load. You add an isFirstRender flag and work out yourself where to flip it: "I'm not gonna tell you where because it's now your job to figure that out on your own."

Build a Memory Game in React, final lesson: preview showing the game-over screen with a Play again button.
The final challenge, solved at 7:57, ends in a game over screen with all ten cards matched and greyed. The GameOver box gets focus so a screen reader announces it, and one Tab reaches Play again.Screenshot of scrimba.com, taken by scrimbaguide.tech.

The outro replaces the usual celebration GIF with an emoji story, because "on a bad day, GIFs can cause some level of motion sickness for me. And since this is my course, then I make the rules." It lists ideas for extending the game: a timer or turn counter, Context, React Router, a redesign, a different API.

What a lesson feels like​

Scrims run from 1:29 to 10:26; most are five to nine minutes. The pattern is stable: a short recap, sometimes a "mini challenge" you answer in your head, then a numbered challenge pasted into the file with hints and a warning about what you will not see yet. You pause, code, and unpause to compare. Ajo's solutions are typed live, typos included, and end with a run in the preview. The tone is warm without being cloying: "give yourself a pat on the back," "please remember to take a break to not wear yourself down completely," and, on getting stuck, "you can always ask Google or ChatGPT. Remember, there's no shame in doing either of that."

The preview pane is small by default; Ajo pops it into a larger window for demos. Every scrim has captions, a timestamped transcript under the settings menu, subtitles in ten languages, and playback speed. Some accessibility results (focus outlines, screen reader output) are not captured in the recording, and Ajo says so and asks you to run the code yourself.

Free or Pro: exactly what is gated​

This is a Pro course. Two scrims are marked SAMPLE and open without a subscription: the 5:31 intro and the 5:49 boilerplate walkthrough. Everything after that, all 29 challenges, the accessibility module, and the certificate, needs Pro. There are no Solo Projects; the whole course is guided.

Pro also unlocks the two career paths this course sits in and the Pro-only Discord channels. Basic Discord access is on the free plan according to Scrimba's pricing page (opens in a new tab), so the community itself is not the upgrade reason; this course and the paths are.

How long it takes​

4.4 hours is video runtime. With 29 challenges to attempt before watching the solution, plan for 9 to 13 hours: a week at an hour and a half a day, or two focused weekends. The accessibility module will take longest if the concepts are new, because you should test with a screen reader (VoiceOver on a Mac, NVDA on Windows) rather than take Ajo's word for it. Doing one of the outro's extension ideas adds a few hours more and makes the project yours.

Who it's for, and who should skip it​

It fits you if you can write a component with useState, have fetched from an API before, and want a finished game that shows you understand accessibility. It also suits anyone who learns by solving small briefs rather than watching long builds.

Skip it for now if hooks and promises are still new; the intro says the course will not teach them, and it does not. Skip it if you want breadth: no routing, state libraries, TypeScript, or testing. And if you are on the fence about Pro, the free Learn React capstones give you two complete games first.

Start Build a Memory Game in React on Scrimba (opens in a new tab)

Prerequisites​

React basics (components, props, useState, useEffect), JavaScript array methods (map, slice, find, includes), destructuring and the spread operator, and async/await with fetch. You do not need any accessibility knowledge; the course teaches aria-label, aria-live, aria-atomic, tabIndex, and programmatic focus from scratch. No local install is needed, and no API key: the EmojiHub API is public.

Where it fits​

Scrimba lists the course under the Frontend Developer Path and the Fullstack Developer Path. It belongs after Learn React and before Advanced React, which covers the patterns this course leaves out. If the accessibility module is the part that lands, Learn Accessible Web Design goes deeper.

Strengths and limits​

What it does well: a high ratio of challenges to lecture, briefs that are specific enough to grade yourself against, accessibility taught as engineering rather than a checklist, an honest instructor who shows their own typos and re-recording seams, and a finished game you can show in a portfolio.

Where it is limited: one project, React 18.2 rather than 19, CSS pre-written so you learn nothing about styling, a small preview pane, some code shown in an older, more verbose form than the re-recorded lessons, and results (focus, screen reader speech) that you have to verify yourself because the recording cannot show them.