The Rules of Hooks

One more hook of your own: useFetch(url) loads a file, as the effects in the Effects lesson did, and returns an object with three values, { data, loading, error }. Lineup.jsx already uses it: it shows Loading the lineup…, the error, or the bands. For now, though, useFetch.js has only the three states, and nothing loads.

Before you finish it, here are the rules that every hook follows, React's and yours:

  1. Call hooks only at the top level of a component or of your own hook: not inside an if, a loop, a handler or another function. Call them every time the component renders, in the same order.
  2. Call hooks only from components and from other hooks, never from ordinary functions.
  3. The names of hooks start with use. That's how React and other tools tell that a function is a hook, and that the rules apply to it.

Why the order? React doesn't know a component's states by their names. It only knows that the component called useState first, second, third, and it keeps their values in that order from one render to the next. If a hook is called only sometimes, the order changes, and React can't tell which value belongs where. So it stops with an error.

That's what happens in News.jsx. Before the news is opened, the component returns early, after one hook. Once it's opened, it gets further and calls useFetch too, which has three more. Click Show the news, and the whole page disappears. The console says why:

React has detected a change in the order of Hooks called by News. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks: https://react.dev/link/rules-of-hooks

   Previous render            Next render
   ------------------------------------------------------
1. useState                   useState
2. undefined                  useState
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Error: Rendered more hooks than during the previous render.
    at useFetch (useFetch.js:4)

The table compares the two renders of News: in the previous one, there was no second hook (undefined), and in this one, there's a useState. The error then names the line where React noticed it: the first useState in useFetch.

The fix: call all the hooks first, and only then return early. If an effect should do its work only sometimes, put the if inside the effect, not around it.

Instructions

Finish useFetch: add an effect that loads url, as in the Effects lesson. It sets loading to true and error to "", loads the file, puts what it read into data and sets loading to false. When the response isn't OK, it puts The data couldn't be loaded. into error instead, and sets loading to false too. The effect uses url, so its dependencies are [url]. Then the lineup shows the bands.

Fix News.jsx: move the line with useFetch above the if, under useState, so that the component calls both hooks every time. Then Show the news shows the three news items. They're even ready before you click: the component now loads them at once.

Start programming for free

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

Or sign up with:

Back

4/5

Next