You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -74,9 +74,10 @@ The resolved value of the Promise.
74
74
#### Caveats {/*promise-caveats*/}
75
75
76
76
* `use` must be called inside a Component or a Hook.
77
+
* Despite its name, `use` is not a Hook. Unlike Hooks, it can be called inside loops and conditional statements like `if`.
77
78
* `use` cannot be called inside a try-catch block. Instead, wrap your component in an [Error Boundary](#displaying-an-error-with-an-error-boundary) to catch the error and display a fallback.
78
79
* Promises passed to `use` must be cached so the same Promise instance is reused across re-renders. [See caching Promises below.](#caching-promises-for-client-components)
79
-
* When passing a Promise from a Server Component to a Client Component, its resolved value must be serializable to pass between server and client. Data types like functions aren't serializable and cannot be the resolved value of such a Promise.
80
+
* When passing a Promise from a Server Component to a Client Component, its resolved value must be [serializable](/reference/rsc/use-client#serializable-types). Data types like functions aren't serializable and cannot be the resolved value of such a Promise.
80
81
81
82
---
82
83
@@ -252,7 +253,7 @@ The component that calls <CodeStep step={1}>`use`</CodeStep> must be wrapped in
252
253
253
254
#### Fetching data with `use` {/*fetching-data-with-use*/}
254
255
255
-
Calling `use` with a cached Promise is the recommended way to fetch data. The component suspends while the Promise is pending, and React displays the nearest Suspense fallback. Rejected Promises propagate to the nearest [Error Boundary](/reference/react/Component#catching-rendering-errors-with-an-error-boundary).
256
+
In this example, `Albums` calls `use` with a cached Promise. The component suspends while the Promise is pending, and React displays the nearest Suspense fallback. Rejected Promises propagate to the nearest [Error Boundary](/reference/react/Component#catching-rendering-errors-with-an-error-boundary).
256
257
257
258
<Sandpack>
258
259
@@ -355,7 +356,7 @@ async function getAlbums() {
355
356
356
357
#### Fetching data with `useEffect` {/*fetching-data-with-useeffect*/}
357
358
358
-
Without`use`, a common approach is to fetch data in an Effect and update state when the data arrives. This requires managing loading and error states manually, and the component renders empty on first paint before the Effect fires.
359
+
Before`use`, a common approach was to fetch data in an Effect and update state when the data arrives. Compared to `use`, this approach requires managing loading and error states manually. For more details on why fetching in an Effect is discouraged, see [You Might Not Need an Effect](/learn/you-might-not-need-an-effect#fetching-data).
359
360
360
361
<Sandpack>
361
362
@@ -439,10 +440,19 @@ export async function fetchAlbums() {
439
440
440
441
Promises created inside a component are recreated on every render. This causes React to show the Suspense fallback repeatedly and prevents content from appearing. Instead, pass a Promise from a cache, a Suspense-enabled framework, or a Server Component.
441
442
443
+
Common ways a Promise can be unintentionally recreated on every render:
444
+
442
445
```js
443
446
functionAlbums() {
444
-
// 🔴 fetch creates a new Promise on every render.
447
+
// 🔴 `fetch` creates a new Promise on every render.
445
448
constalbums=use(fetch('/albums'));
449
+
450
+
// 🔴 Calling an async function creates a new Promise on every render.
451
+
constalbums=use(getAlbums());
452
+
453
+
// 🔴 Adding `.then` returns a new Promise on every render,
Ideally, Promises are created before rendering — such as in an event handler, a route loader, or a Server Component — and passed to the component that calls `use`. Fetching lazily in render delays network requests and can create waterfalls.
465
+
Ideally, Promises are created before rendering, such as in an event handler, a route loader, or a Server Component, and passed to the component that calls `use`. Fetching lazily in render delays network requests and can create waterfalls.
456
466
457
467
</Pitfall>
458
468
@@ -478,10 +488,12 @@ The `fetchData` function returns the same Promise each time it's called with the
478
488
479
489
<Note>
480
490
481
-
The way you cache Promises depends on the framework you use with Suspense. Frameworks typically provide built-in caching mechanisms. If you don't use a framework, you can use a simple module-level cache like the one above, or a library that supports Suspense-compatible caching.
491
+
The way you cache Promises depends on the framework you use with Suspense. Frameworks typically provide built-in caching mechanisms. If you don't use a framework, you can use a simple module-level cache like the one above, or a [Suspense-enabled data source](/reference/react/Suspense#displaying-a-fallback-while-content-is-loading).
482
492
483
493
</Note>
484
494
495
+
In the example below, clicking "Re-render" updates state in `App` and triggers a re-render. Because `fetchData` returns the same cached Promise, `Albums` reads the value synchronously instead of showing the Suspense fallback again.
496
+
485
497
<Sandpack>
486
498
487
499
```js src/App.js active
@@ -567,7 +579,7 @@ async function getAlbums() {
567
579
568
580
#### How to implement a promise cache {/*how-to-implement-a-promise-cache*/}
569
581
570
-
A basic cache stores the Promise keyed by URL so the same instance is reused across renders. To also avoid unnecessary Suspense fallbacks when data is already available, you can set `status` and `value` (or `reason`) fields on the Promise. React checks these fields when `use` is called — if `status` is `'fulfilled'`, it reads `value` synchronously without suspending. If `status` is `'rejected'`, it throws `reason`. If the field is missing or `'pending'`, it suspends.
582
+
A basic cache stores the Promise keyed by URL so the same instance is reused across renders. To also avoid unnecessary Suspense fallbacks when data is already available, you can set `status` and `value` (or `reason`) fields on the Promise. React checks these fields when `use` is called: if `status` is `'fulfilled'`, it reads `value` synchronously without suspending. If `status` is `'rejected'`, it throws `reason`. If the field is missing or `'pending'`, it suspends.
Frameworks that support Suspense typically provide their own caching and invalidation mechanisms. Building a custom cache like the one above is useful for understanding the pattern, but in practice you should use your framework's data fetching solution.
773
+
Frameworks that support Suspense typically provide their own caching and invalidation mechanisms. The custom cache above is useful for understanding the pattern, but in practice prefer your framework's data fetching solution.
762
774
763
775
</Note>
764
776
@@ -887,7 +899,7 @@ async function getData(url) {
887
899
asyncfunctiongetAlbums(artistId) {
888
900
// Add a fake delay to make waiting noticeable.
889
901
awaitnewPromise(resolve=> {
890
-
setTimeout(resolve, 80);
902
+
setTimeout(resolve, 800);
891
903
});
892
904
893
905
if (artistId ==='the-beatles') {
@@ -1047,16 +1059,33 @@ root.render(
1047
1059
1048
1060
#### Should I resolve a Promise in a Server or Client Component? {/*resolve-promise-in-server-or-client-component*/}
1049
1061
1050
-
A Promise can be passed from a Server Component to a Client Component and resolved in the Client Component with the `use` API. You can also resolve the Promise in a Server Component with `await` and pass the required data to the Client Component as a prop.
1062
+
A Promise can be passed from a Server Component to a Client Component and resolved in the Client Component with the `use` API. You can also resolve the Promise in a Server Component with `await` and pass the resolved value to the Client Component as a prop. The difference comes down to how much of your UI you want to reveal before the data is ready.
1063
+
1064
+
Using `await` in a [Server Component](/reference/rsc/server-components) suspends the Server Component itself, so React won't continue rendering it until the Promise resolves:
Passing the Promise to a Client Component doesn't suspend the Server Component. The Server Component returns immediately, and the Client Component suspends when it calls `use`:
But using `await` in a [Server Component](/reference/rsc/server-components) will block its rendering until the `await` statement is finished. Passing a Promise from a Server Component to a Client Component prevents the Promise from blocking the rendering of the Server Component.
1084
+
In both cases, the component that reads the Promise suspends. Make sure there's a [`<Suspense>`](/reference/react/Suspense) boundary above it so React can display a fallback there and keep rendering the rest of the page. Without a boundary above the suspending component, the suspension bubbles up the tree and blocks the surrounding UI until the Promise resolves.
1085
+
1086
+
Passing the Promise down is useful when a Client Component needs the data and you want to reveal as much of the surrounding UI as possible while the Promise is pending. Because the Client Component is the component that suspends, you can place the `<Suspense>` boundary close to it and let the rest of the page render right away. See [Displaying a fallback while content is loading](/reference/react/Suspense#displaying-a-fallback-while-content-is-loading) for more on boundary placement.
1087
+
1088
+
When the surrounding UI is small or depends on the same data, prefer `await` on the server. If a Server Component above already awaits the data, pass the resolved value down instead of creating a new Promise to call `use`.
1060
1089
1061
1090
</DeepDive>
1062
1091
@@ -1066,36 +1095,40 @@ But using `await` in a [Server Component](/reference/rsc/server-components) will
1066
1095
1067
1096
If the Promise passed to `use` is rejected, the error propagates to the nearest [Error Boundary](/reference/react/Component#catching-rendering-errors-with-an-error-boundary). Wrap the component that calls `use` in an Error Boundary to display a fallback when the Promise is rejected.
1068
1097
1098
+
In the example below, `fetchData` rejects on the first attempt and succeeds on retry. The Error Boundary catches the rejection and shows a fallback with a "Try again" button.
0 commit comments