Congratulations!

Congratulations, your flashcards work, and you've reached the end of the React course! The app loads its words from a file, turns the cards over, goes through the deck, counts what you know, adds your own words and checks them, remembers it all for next time and lets you practice what you don't know yet. And you built all of it yourself.

One last improvement. The words you know have disappeared from the cards, so it would be nice to see them somewhere. Show them in a list under the buttons. The list is computed like toLearn, only with the opposite condition, and map() turns it into li elements, each with its key:

const knownWords = deck.filter((word) => known.includes(word.id));
<ul className="known-words">
    {knownWords.map((word) => (
        <li key={word.id}>
            {word.spanish}: {word.english}
        </li>
    ))}
</ul>

If you like, add a heading such as Words you know above it, and show both only when the list isn't empty: knownWords.length > 0 && …, not knownWords.length && …, which would show a 0.

What you've learned. Every part of the course has found its place in your app:

  • Components: the app is made of App, Flashcard and WordForm, each in its own file, connected with export default and import.
  • JSX: the markup right in JavaScript, with className and values in curly braces.
  • Props: Flashcard gets its word and translation, and WordForm the function onAdd.
  • Lists and conditions: filter(), and map() with key, the conditional operator for the side and the class of the card, and an early return for loading, for an error and for the end.
  • Events: onClick, onChange, and onSubmit with preventDefault().
  • State: whether the card is turned over, the index, the words and what you know. Arrays in state are never changed in place.
  • Forms: controlled fields that check what you type and show an error message.
  • Sharing state: the words live in App, which gives the form a function to add one. The deck, the position, the score and the cards left to learn are computed, not stored.
  • Effects: fetch() in an effect loads words.json, with Loading… and an error message.
  • Custom hooks: useLocalStorage remembers what you know, and all the hooks are at the top of the component.

React on your own computer. In the exercises, our site did what a tool called Vite (French for "quick", pronounced "veet") does on your computer: it turned the JSX into JavaScript and connected the files. That's how real React projects are usually made. You need Node.js (take the LTS version), which comes with npm, a program for installing packages (ready-made programs and libraries), and the terminal (the command line). Open the terminal in the folder where you want the project, and run:

npm create vite@latest flashcards

Vite asks a few questions. Choose the framework React and the variant JavaScript. When it offers to install the project and start it now, answer No, so that you can do it yourself; for any other question, the answer it suggests is fine. Then go into the new folder, install the packages and start the project:

cd flashcards
npm install
npm run dev

npm install downloads React, Vite and what they need into the folder node_modules. npm run dev starts Vite's development server and shows the address of your app, http://localhost:5173/. Open it in the browser. Whenever you save a file, the page updates by itself. The server runs until you stop it with Ctrl+C in the terminal.

The project's files are laid out like the files of the exercises, only the JavaScript is in the folder src. Copy your app into the project:

  • index.html is in the project's folder, with <div id="root"> and a script that loads /src/main.jsx. Leave it as it is, except for the title.
  • src/main.jsx renders <App />, as yours does, only it imports ./index.css. Change that to ./style.css.
  • src/App.jsx is the App component. Replace its code with yours, and save Flashcard.jsx, WordForm.jsx, useLocalStorage.js and style.css next to it in src.
  • public is for files that go online as they are, which the app gets by their address. Save words.json there, and fetch("words.json") finds it.

Vite's example also has App.css, index.css and the folder assets in src. Your app doesn't use them, so you can delete them. And package.json lists the project's packages and its commands, such as dev and build.

StrictMode. In Vite's main.jsx, <App /> is wrapped in StrictMode. (Vite also writes texts in single quotes and leaves out the semicolons, which works just as well.)

import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.jsx'

createRoot(document.getElementById('root')).render(
  <StrictMode>
    <App />
  </StrictMode>,
)

StrictMode changes nothing on the page. It turns on extra checks while you develop: React renders every component twice, and it runs every effect, cleans it up and runs it again, as if the component appeared, disappeared and appeared again. That way, an effect without a cleanup shows its mistake right away: an interval without clearInterval() would run twice. We left StrictMode out of the exercises because with it, a console.log() in an effect prints everything twice, which is confusing when you're starting. In your project, keep it. Your app works with it: the effect just loads the words twice, which does no harm. The checks only run in development, not in the finished app.

Putting it online. npm run build makes the finished app in the folder dist: index.html, the files from public, and in assets your JavaScript and CSS, put together and without JSX, ready for browsers. npm run preview lets you try it first. dist is an ordinary website that any web hosting can serve. On Netlify Drop, you drag the folder onto the page, and your app gets an address on the internet (to keep it there, you sign up for free). Netlify and Vercel can also take your project from GitHub and build it themselves after every change.

React Developer Tools is an extension for Chrome, Firefox and Edge. In the browser's developer tools (F12, on a Mac Cmd+Option+I), it adds the tab Components with the tree of your components: click one, and you'll see its props, its state and its other hooks, and you can even change them to see what happens.

What's next. Some ideas:

  • Keep improving your flashcards. You know everything these need: a button that removes one of your own words, cards the other way round (English first), shuffling the deck, a ref that puts the cursor back into the first field after adding a word, or several decks (animals.json, food.json) with a select and an effect that loads the chosen one.
  • React's documentation at react.dev explains everything from this course in more depth, with exercises, and describes every hook.
  • Context and useReducer: context passes data to components deep down without going through the props of every component on the way, and useReducer keeps state with many kinds of changes in one place.
  • Form actions are new in React 19: a function in <form action={…}> gets the data of the form, and useActionState and useFormStatus tell you whether it's still being sent and how it went.
  • React Router gives an app several pages with addresses of their own, such as / and /words.
  • TypeScript describes what's in the props and the state, and finds many mistakes before you even run the app. Vite has the variant TypeScript for it, and the TypeScript course teaches it.
  • Next.js is a framework built on React for whole websites: pages in files, rendering on the server and loading data. This website is built with it, too.

Instructions

Under the buttons, show the words you know in <ul className="known-words">, one li per word with its key, as above. Mark a word with I know it, and it appears in the list.

Start programming for free

By signing up, you agree to the Terms of Service and Privacy Policy.

Or sign up with:

Back

8/8