# A Beginner's Guide to React 19's New use API

%%[kempo] 

One of the new features in React 19 is the `use` API.

The basic idea is that the `use` API can fetch resources *during* React's render cycle. Instead of doing something like fetching data in an effect and updating the component state, we can get the data directly via the `use` API.

When paired with React's `Suspense` component, we can easily manage conditional rendering:

<iframe src="https://kempo.io/view/eyJpZCI6ImtsX3Vvd2YxdXc3aDdqZmk0Y2pxNWllcXByZyIsIm5hbWUiOiJSZWFjdCAxOSB1c2UgQVBJIiwiY29yZSI6eyJmaWxlcyI6eyIvc3R5bGVzLmNzcyI6eyJjb2RlIjoiYm9keSB7XG4gIGZvbnQtZmFtaWx5OiBzYW5zLXNlcmlmO1xuICAtd2Via2l0LWZvbnQtc21vb3RoaW5nOiBhdXRvO1xuICAtbW96LWZvbnQtc21vb3RoaW5nOiBhdXRvO1xuICAtbW96LW9zeC1mb250LXNtb290aGluZzogZ3JheXNjYWxlO1xuICBmb250LXNtb290aGluZzogYXV0bztcbiAgdGV4dC1yZW5kZXJpbmc6IG9wdGltaXplTGVnaWJpbGl0eTtcbiAgZm9udC1zbW9vdGg6IGFsd2F5cztcbiAgLXdlYmtpdC10YXAtaGlnaGxpZ2h0LWNvbG9yOiB0cmFuc3BhcmVudDtcbiAgLXdlYmtpdC10b3VjaC1jYWxsb3V0OiBub25lO1xuICBwYWRkaW5nOiAycmVtO1xufVxuXG5oMSB7XG4gIGZvbnQtc2l6ZTogMS41cmVtO1xufVxuXG5oMiB7XG4gIGZvbnQtc2l6ZTogMS4yNXJlbTtcbn1cblxuZm9ybSB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGdhcDogMC41cmVtO1xufVxuXG5mb3JtIGJ1dHRvbiB7XG4gIGFsaWduLXNlbGY6IGZsZXgtZW5kO1xufVxuXG5sYWJlbCB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gIGdhcDogMC4xMjVyZW07XG59XG5cbi5wb3N0LXdyYXBwZXIsXG4uY29tbWVudC13cmFwcGVyIHtcbiAgZGlzcGxheTogZmxleDtcbiAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbn1cblxuLnBvc3Qtd3JhcHBlciBkaXYge1xuICBkaXNwbGF5OiBmbGV4O1xuICBhbGlnbi1pdGVtczogYmFzZWxpbmU7XG4gIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2Vlbjtcbn1cbiJ9LCIvdHNjb25maWcuanNvbiI6eyJjb2RlIjoie1xuICBcImluY2x1ZGVcIjogW1xuICAgIFwiLi8qKi8qXCJcbiAgXSxcbiAgXCJjb21waWxlck9wdGlvbnNcIjoge1xuICAgIFwic3RyaWN0XCI6IHRydWUsXG4gICAgXCJlc01vZHVsZUludGVyb3BcIjogdHJ1ZSxcbiAgICBcImxpYlwiOiBbIFwiZG9tXCIsIFwiZXMyMDE1XCIgXSxcbiAgICBcImpzeFwiOiBcInJlYWN0LWpzeFwiXG4gIH1cbn0ifSwiL0FwcC50c3giOnsiY29kZSI6ImltcG9ydCB7IHVzZSwgU3VzcGVuc2UgfSBmcm9tIFwicmVhY3RcIjtcbmltcG9ydCB7IFBvc3QgfSBmcm9tIFwiLi91dGlsc1wiO1xuXG5leHBvcnQgZnVuY3Rpb24gQ29tbWVudHMoeyBnZXRDb21tZW50c1Byb21pc2UgfSkge1xuICBjb25zdCBjb21tZW50cyA9IHVzZShnZXRDb21tZW50c1Byb21pc2UpO1xuXG4gIHJldHVybiBjb21tZW50cy5tYXAoKGNvbW1lbnQpID0+IDxwIGtleT17Y29tbWVudC5pZH0+e2NvbW1lbnQuY29tbWVudH08L3A+KTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gQXBwKHsgZ2V0Q29tbWVudHNQcm9taXNlIH0pOiBKU1guRWxlbWVudCB7XG4gIHJldHVybiAoXG4gICAgPD5cbiAgICAgIDxQb3N0IC8+XG4gICAgICA8ZGl2IGNsYXNzTmFtZT1cImNvbW1lbnRzLXdyYXBwZXJcIj5cbiAgICAgICAgPGgyPkNvbW1lbnRzPC9oMj5cblxuICAgICAgICA8U3VzcGVuc2UgZmFsbGJhY2s9e1wiQ29tbWVudHMgTG9hZGluZy4uLlwifT5cbiAgICAgICAgICA8Q29tbWVudHMgZ2V0Q29tbWVudHNQcm9taXNlPXtnZXRDb21tZW50c1Byb21pc2V9IC8+XG4gICAgICAgIDwvU3VzcGVuc2U+XG4gICAgICA8L2Rpdj5cbiAgICA8Lz5cbiAgKTtcbn1cbiJ9LCIvaW5kZXgudHN4Ijp7ImNvZGUiOiJpbXBvcnQgUmVhY3QsIHsgU3RyaWN0TW9kZSB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgY3JlYXRlUm9vdCB9IGZyb20gXCJyZWFjdC1kb20vY2xpZW50XCI7XG5cbmltcG9ydCBcIi4vc3R5bGVzLmNzc1wiO1xuXG5pbXBvcnQgQXBwIGZyb20gXCIuL0FwcFwiO1xuaW1wb3J0IHsgc2xlZXAgfSBmcm9tIFwiLi91dGlsc1wiO1xuXG5jb25zdCBnZXRDb21tZW50cyA9IGFzeW5jICgpID0+IHtcbiAgYXdhaXQgc2xlZXAoMjAwMCk7XG5cbiAgY29uc3QgdXJsID0gbmV3IFVSTChkb2N1bWVudC5sb2NhdGlvbik7XG5cbiAgcmV0dXJuIFtcbiAgICB7IGlkOiAxLCBjb21tZW50OiBcIlRoaXMgaXMgYSBjb21tZW50XCIgfSxcbiAgICB7IGlkOiAxLCBjb21tZW50OiBcIlRoaXMgaXMgYW5vdGhlciBjb21tZW50XCIgfSxcbiAgXTtcbn07XG5cbmNvbnN0IHJvb3QgPSBjcmVhdGVSb290KGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwicm9vdFwiKSk7XG5yb290LnJlbmRlcig8QXBwIGdldENvbW1lbnRzUHJvbWlzZT17Z2V0Q29tbWVudHMoKX0gLz4pO1xuIn0sIi9wdWJsaWMvaW5kZXguaHRtbCI6eyJjb2RlIjoiPCFET0NUWVBFIGh0bWw+XG48aHRtbCBsYW5nPVwiZW5cIj5cbiAgPGhlYWQ+XG4gICAgPG1ldGEgY2hhcnNldD1cIlVURi04XCI+XG4gICAgPG1ldGEgbmFtZT1cInZpZXdwb3J0XCIgY29udGVudD1cIndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xLjBcIj5cbiAgICA8dGl0bGU+RG9jdW1lbnQ8L3RpdGxlPlxuICA8L2hlYWQ+XG4gIDxib2R5PlxuICAgIDxkaXYgaWQ9XCJyb290XCI+PC9kaXY+XG4gIDwvYm9keT5cbjwvaHRtbD4ifSwiL3BhY2thZ2UuanNvbiI6eyJjb2RlIjoie1xuICBcImRlcGVuZGVuY2llc1wiOiB7XG4gICAgXCJyZWFjdFwiOiBcIjE5LjAuMC1iZXRhLTI2ZjI0OTYwOTMtMjAyNDA1MTRcIixcbiAgICBcInJlYWN0LWRvbVwiOiBcIjE5LjAuMC1iZXRhLTI2ZjI0OTYwOTMtMjAyNDA1MTRcIixcbiAgICBcInJlYWN0LXNjcmlwdHNcIjogXCJeNS4wLjBcIixcbiAgICBcInJlYWN0LWVycm9yLWJvdW5kYXJ5XCI6IFwiNC4wLjEzXCJcbiAgfSxcbiAgXCJkZXZEZXBlbmRlbmNpZXNcIjoge1xuICAgIFwiQHR5cGVzL3JlYWN0XCI6IFwiXjE4LjAuMFwiLFxuICAgIFwiQHR5cGVzL3JlYWN0LWRvbVwiOiBcIl4xOC4wLjBcIixcbiAgICBcInR5cGVzY3JpcHRcIjogXCJeNC4wLjBcIlxuICB9LFxuICBcIm1haW5cIjogXCIvaW5kZXgudHN4XCJcbn0ifSwiL3V0aWxzLnRzeCI6eyJjb2RlIjoiZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNsZWVwKHRpbWVvdXQ6IG51bWJlcikge1xuICByZXR1cm4gYXdhaXQgbmV3IFByb21pc2UoKHIpID0+IHNldFRpbWVvdXQociwgdGltZW91dCkpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gUG9zdCgpIHtcbiAgcmV0dXJuIChcbiAgICA8ZGl2IGNsYXNzTmFtZT1cInBvc3Qtd3JhcHBlclwiPlxuICAgICAgPGgxPk15IFBvc3Q8L2gxPlxuXG4gICAgICA8cD5UaGlzIGlzIG15IHBvc3QgY29udGVudDwvcD5cbiAgICA8L2Rpdj5cbiAgKTtcbn1cbiJ9fSwidGVtcGxhdGUiOiJyZWFjdC10cyJ9LCJkaXNwbGF5Ijp7ImNvbXBvbmVudHMiOnsiRWRpdG9yIjp7InR5cGUiOiJlZGl0b3IiLCJkYXRhIjp7InNob3dUYWJzIjpmYWxzZSwic2hvd0xpbmVOdW1iZXJzIjp0cnVlLCJzaG93SW5saW5lRXJyb3JzIjpmYWxzZSwic2hvd1J1bkJ1dHRvbiI6dHJ1ZSwid3JhcENvbnRlbnQiOnRydWUsImNsb3NhYmxlVGFicyI6ZmFsc2UsInJlYWRPbmx5Ijp0cnVlLCJzaG93UmVhZE9ubHkiOnRydWV9fSwiUHJldmlldyI6eyJ0eXBlIjoicHJldmlldyIsImRhdGEiOnsic2hvd05hdmlnYXRvciI6ZmFsc2UsInNob3dPcGVuSW5Db2RlU2FuZGJveCI6ZmFsc2UsInNob3dSZWZyZXNoQnV0dG9uIjp0cnVlLCJzaG93U2FuZHBhY2tFcnJvck92ZXJsYXkiOmZhbHNlfX19LCJnZW5lcmFsIjp7InZpc2libGVGaWxlcyI6WyIvQXBwLnRzeCJdLCJ0aGVtZSI6ImtlbXBvRGFyayJ9LCJsYXlvdXRzIjp7InNtYWxsIjoiJ0VkaXRvcidcbidQcmV2aWV3JyJ9fX0=" height="750px" width="100%"></iframe>

In the example above, the `App` component gets a `getCommentsPromise`, which is eventually passed to the `use` API in the `Comments` component. The promise takes some time to resolve, which means we should probably show a loading state.

The good news is that we don't have to manage this ourselves. Because the `use` API works seamlessly with the `Suspense` component, we can provide a `fallback` and things just work!

### Context values can be conditionally loaded with the `use` API.

Normally, you would need to use the `useContext` hook to get the value of a Context provider. The problem with this approach is that this hook has to follow the [Rules of Hooks](https://react.dev/warnings/invalid-hook-call-warning).

The relevant rule is that we can't call a hook *conditionally*.

The `use` API, on the other hand, doesn't have this restriction. We are free to load a Context value however we want:

<iframe src="https://kempo.io/view/eyJpZCI6ImtsX3Vvd2YxdXc3aDdqZmk0Y2pxNWllcXByZyIsIm5hbWUiOiJSZWFjdCAxOSB1c2UgQVBJIiwiY29yZSI6eyJmaWxlcyI6eyIvc3R5bGVzLmNzcyI6eyJjb2RlIjoiYm9keSB7XG4gIGZvbnQtZmFtaWx5OiBzYW5zLXNlcmlmO1xuICAtd2Via2l0LWZvbnQtc21vb3RoaW5nOiBhdXRvO1xuICAtbW96LWZvbnQtc21vb3RoaW5nOiBhdXRvO1xuICAtbW96LW9zeC1mb250LXNtb290aGluZzogZ3JheXNjYWxlO1xuICBmb250LXNtb290aGluZzogYXV0bztcbiAgdGV4dC1yZW5kZXJpbmc6IG9wdGltaXplTGVnaWJpbGl0eTtcbiAgZm9udC1zbW9vdGg6IGFsd2F5cztcbiAgLXdlYmtpdC10YXAtaGlnaGxpZ2h0LWNvbG9yOiB0cmFuc3BhcmVudDtcbiAgLXdlYmtpdC10b3VjaC1jYWxsb3V0OiBub25lO1xuICBwYWRkaW5nOiAycmVtO1xufVxuIn0sIi90c2NvbmZpZy5qc29uIjp7ImNvZGUiOiJ7XG4gIFwiaW5jbHVkZVwiOiBbXG4gICAgXCIuLyoqLypcIlxuICBdLFxuICBcImNvbXBpbGVyT3B0aW9uc1wiOiB7XG4gICAgXCJzdHJpY3RcIjogdHJ1ZSxcbiAgICBcImVzTW9kdWxlSW50ZXJvcFwiOiB0cnVlLFxuICAgIFwibGliXCI6IFsgXCJkb21cIiwgXCJlczIwMTVcIiBdLFxuICAgIFwianN4XCI6IFwicmVhY3QtanN4XCJcbiAgfVxufSJ9LCIvQXBwLnRzeCI6eyJjb2RlIjoiaW1wb3J0IHsgdXNlIH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgeyBVc2VyQ29udGV4dCB9IGZyb20gXCIuL3V0aWxzXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBVc2VyQmFubmVyKHsgc2hvd1VzZXIgfSkge1xuICBpZiAoIXNob3dVc2VyKSByZXR1cm4gPHA+SGkgVW5rbm93biE8L3A+O1xuXG4gIGNvbnN0IHVzZXIgPSB1c2UoVXNlckNvbnRleHQpO1xuICByZXR1cm4gPGRpdj5IaSB7dXNlcn0hPC9kaXY+O1xufVxuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBBcHAoKTogSlNYLkVsZW1lbnQge1xuICByZXR1cm4gKFxuICAgIDxVc2VyQ29udGV4dC5Qcm92aWRlciB2YWx1ZT1cIkNvbnRleHQgVXNlclwiPlxuICAgICAgPFVzZXJCYW5uZXIgLz5cbiAgICAgIDxVc2VyQmFubmVyIHNob3dVc2VyIC8+XG4gICAgPC9Vc2VyQ29udGV4dC5Qcm92aWRlcj5cbiAgKTtcbn1cbiJ9LCIvaW5kZXgudHN4Ijp7ImNvZGUiOiJpbXBvcnQgUmVhY3QsIHsgU3RyaWN0TW9kZSB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgY3JlYXRlUm9vdCB9IGZyb20gXCJyZWFjdC1kb20vY2xpZW50XCI7XG5cbmltcG9ydCBcIi4vc3R5bGVzLmNzc1wiO1xuXG5pbXBvcnQgQXBwIGZyb20gXCIuL0FwcFwiO1xuXG5jb25zdCByb290ID0gY3JlYXRlUm9vdChkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInJvb3RcIikpO1xucm9vdC5yZW5kZXIoPEFwcCAvPik7XG4ifSwiL3B1YmxpYy9pbmRleC5odG1sIjp7ImNvZGUiOiI8IURPQ1RZUEUgaHRtbD5cbjxodG1sIGxhbmc9XCJlblwiPlxuICA8aGVhZD5cbiAgICA8bWV0YSBjaGFyc2V0PVwiVVRGLThcIj5cbiAgICA8bWV0YSBuYW1lPVwidmlld3BvcnRcIiBjb250ZW50PVwid2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEuMFwiPlxuICAgIDx0aXRsZT5Eb2N1bWVudDwvdGl0bGU+XG4gIDwvaGVhZD5cbiAgPGJvZHk+XG4gICAgPGRpdiBpZD1cInJvb3RcIj48L2Rpdj5cbiAgPC9ib2R5PlxuPC9odG1sPiJ9LCIvcGFja2FnZS5qc29uIjp7ImNvZGUiOiJ7XG4gIFwiZGVwZW5kZW5jaWVzXCI6IHtcbiAgICBcInJlYWN0XCI6IFwiMTkuMC4wLWJldGEtMjZmMjQ5NjA5My0yMDI0MDUxNFwiLFxuICAgIFwicmVhY3QtZG9tXCI6IFwiMTkuMC4wLWJldGEtMjZmMjQ5NjA5My0yMDI0MDUxNFwiLFxuICAgIFwicmVhY3Qtc2NyaXB0c1wiOiBcIl41LjAuMFwiLFxuICAgIFwicmVhY3QtZXJyb3ItYm91bmRhcnlcIjogXCI0LjAuMTNcIlxuICB9LFxuICBcImRldkRlcGVuZGVuY2llc1wiOiB7XG4gICAgXCJAdHlwZXMvcmVhY3RcIjogXCJeMTguMC4wXCIsXG4gICAgXCJAdHlwZXMvcmVhY3QtZG9tXCI6IFwiXjE4LjAuMFwiLFxuICAgIFwidHlwZXNjcmlwdFwiOiBcIl40LjAuMFwiXG4gIH0sXG4gIFwibWFpblwiOiBcIi9pbmRleC50c3hcIlxufSJ9LCIvdXRpbHMudHN4Ijp7ImNvZGUiOiJpbXBvcnQgeyBjcmVhdGVDb250ZXh0IH0gZnJvbSBcInJlYWN0XCI7XG5cbmV4cG9ydCBjb25zdCBVc2VyQ29udGV4dCA9IGNyZWF0ZUNvbnRleHQoKTtcbiJ9fSwidGVtcGxhdGUiOiJyZWFjdC10cyJ9LCJkaXNwbGF5Ijp7ImNvbXBvbmVudHMiOnsiRWRpdG9yIjp7InR5cGUiOiJlZGl0b3IiLCJkYXRhIjp7InNob3dUYWJzIjpmYWxzZSwic2hvd0xpbmVOdW1iZXJzIjp0cnVlLCJzaG93SW5saW5lRXJyb3JzIjpmYWxzZSwic2hvd1J1bkJ1dHRvbiI6dHJ1ZSwid3JhcENvbnRlbnQiOnRydWUsImNsb3NhYmxlVGFicyI6ZmFsc2UsInJlYWRPbmx5Ijp0cnVlLCJzaG93UmVhZE9ubHkiOnRydWV9fSwiUHJldmlldyI6eyJ0eXBlIjoicHJldmlldyIsImRhdGEiOnsic2hvd05hdmlnYXRvciI6ZmFsc2UsInNob3dPcGVuSW5Db2RlU2FuZGJveCI6ZmFsc2UsInNob3dSZWZyZXNoQnV0dG9uIjp0cnVlLCJzaG93U2FuZHBhY2tFcnJvck92ZXJsYXkiOmZhbHNlfX19LCJnZW5lcmFsIjp7InZpc2libGVGaWxlcyI6WyIvQXBwLnRzeCJdLCJ0aGVtZSI6ImtlbXBvRGFyayJ9LCJsYXlvdXRzIjp7InNtYWxsIjoiJ0VkaXRvcidcbidFZGl0b3InXG4nUHJldmlldycifX19" height="750px" width="100%"></iframe>

In this example, notice how the `UserBanner` component *reads* the `UserContext` value *if* the `showUser` prop is `true`. In other words, if this prop is `false`, then we *don't* call the `use` API.

This is the key difference!

If we were to use the `useContext` hook, then we wouldn't be able to do this. We would have to put the hook at the top of the component and *always* read the context value regardless of whether we use it in the final JSX.

### How do you handle errors?

So what if the resource you're loading throws an error? Maybe there's an auth error or a timeout. The good news is that handling an error with the `use` API is straightforward!

You have two main options:

1. Use an error boundary
    
2. Catch the error and return a different value
    

Here's an example using an error boundary:

```javascript
import { use, Suspense } from 'react';
import { ErrorBoundary } from 'react-error-boundary';

export function Comments({ getCommentsPromise }) {
  return (
    <ErrorBoundary fallback={<p>Oh no! Something went wrong!</p>}>
      <Suspense fallback={<p>Fetching Comments!</p>}>
        <Comment commentPromise={getCommentsPromise} />
      </Suspense>
    </ErrorBoundary>
  );
}

function Comment({ commentPromise }) {
  const comment = use(commentPromise);
  return <p>{comment}</p>;
}
```

### The `use` API must be called within the render cycle.

One thing to keep in mind is that the `use` API has to be called in a component's render cycle. This is similar to hooks. The key difference is that you can leverage the `use` API conditionally. Outside of that, you can also easily manage loading and error states.

And that's it!

React 19's `use` API is a simple and powerful tool to handle loading data asynchronously, loading context values, and conditionally rendering JSX.
