Words from a File

One card isn't a deck yet. The words for the deck are in the file words.json, in the last tab of the editor: twelve objects, each with an id, the Spanish word in spanish and the English one in english. The first two look like this:

[
    { "id": 1, "spanish": "el gato", "english": "cat" },
    { "id": 2, "spanish": "el perro", "english": "dog" },
    …
]

You'll load them as in the Effects lesson: with fetch() in an effect whose dependencies are [], so that it runs once, after App first appears. Until the words arrive, there's nothing to show. So the state words starts as null, and while it is, App returns just a message, before it gets to the card:

if (words === null) {
    return <p>Loading…</p>;
}

const card = words[0];

Below the check, the words are there, and card is the first of them. Its properties go to the card as props: <Flashcard word={card.spanish} translation={card.english} />.

In the Effects lesson, a state of its own, loading, said whether the data was still on its way. Here, words says it by itself: it's null until the words arrive, and an array after that. So it needs no second state.

And if the file can't be loaded? Then words stays null, and the app would say Loading… forever. It's better to say what happened: a second state, error, gets a message, and App shows it. Check it before words === null, because after a failed load, both are true.

Typical mistakes:

  • Putting useState or useEffect below the ifs. React needs to call the same hooks in the same order on every render, and the early return would skip them. Hooks always go at the top of the component.
  • Leaving out the [] at the end of useEffect. The effect then runs after every render: it loads the words, setWords() renders again, and the effect loads them again, over and over.
  • Reading words[0] above the check. The first render then ends with TypeError: Cannot read properties of null (reading '0').

Instructions

In App.jsx, add the state words, null at first, and an effect that loads words.json and puts the words into it with setWords(). While words is null, return <p>Loading…</p>. After that, show the card of the first word, words[0], instead of the dog. The page shows Loading… for a moment, and then a card with el gato.

Add the state error, an empty text at first. If response.ok is false, put The words couldn't be loaded. into it with setError() and end the function with return. Above the check for null, return <p className="error">{error}</p> when error isn't empty. Try it: change the name in fetch() to wordz.json, a file that doesn't exist, run the code, and then change it back.

Start programming for free

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

Or sign up with:

Back

2/8

Next