diff --git a/src/components/ButtonLink.tsx b/src/components/ButtonLink.tsx
index bd98d5b3..dff09ed3 100644
--- a/src/components/ButtonLink.tsx
+++ b/src/components/ButtonLink.tsx
@@ -33,7 +33,7 @@ function ButtonLink({
className,
'active:scale-[.98] transition-transform inline-flex font-bold items-center outline-none focus:outline-none focus-visible:outline focus-visible:outline-link focus:outline-offset-2 focus-visible:dark:focus:outline-link-dark leading-snug',
{
- 'bg-link text-white dark:bg-brand-dark dark:text-secondary hover:bg-opacity-80':
+ 'bg-link text-white dark:bg-brand-dark dark:text-gray-90 hover:bg-opacity-80':
type === 'primary',
'text-primary dark:text-primary-dark shadow-secondary-button-stroke dark:shadow-secondary-button-stroke-dark hover:bg-gray-40/5 active:bg-gray-40/10 hover:dark:bg-gray-60/5 active:dark:bg-gray-60/10':
type === 'secondary',
diff --git a/src/content/learn/editor-setup.md b/src/content/learn/editor-setup.md
index 50d6e17f..024207dd 100644
--- a/src/content/learn/editor-setup.md
+++ b/src/content/learn/editor-setup.md
@@ -31,11 +31,7 @@ Baadhi ya vihariri huja na maumbile haya yakiwa yamejengwa ndani, lakini vingine
### Linting {/*linting*/}
-<<<<<<< HEAD
Code linters hupata matatizo katika kodi yako unapoandika, zikikusaidia kuyarekebisha mapema. [ESLint](https://eslint.org/) ni linter maarufu ya chanzo wazi (open source) kwa ajili ya JavaScript.
-=======
-Code linters find problems in your code as you write, helping you fix them early. [ESLint](https://eslint.org/) is a popular, open source linter for JavaScript.
->>>>>>> 8bb31acb86bf68fa33d97dd0f1b834dfa71e2b1a
* [Sakinisha ESLint kwa mpangilio uliopendekezwa kwa React](https://www.npmjs.com/package/eslint-config-react-app) (hakikisha una [Node imesakinishwa!](https://nodejs.org/en/download/current/))
* [Unganisha ESLint katika VSCode na kiendelezi rasmi](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)
diff --git a/src/content/learn/thinking-in-react.md b/src/content/learn/thinking-in-react.md
index ef1f2482..7019c18f 100644
--- a/src/content/learn/thinking-in-react.md
+++ b/src/content/learn/thinking-in-react.md
@@ -37,15 +37,9 @@ Anza kwa kuchora visanduku kuzunguka kila kijenzi na kijenzi kidogo kwenye kiigi
Kulingana na msingi wako, unaweza kufikiria kugawanya muundo katika vijenzi kwa njia tofauti:
-<<<<<<< HEAD
* **Programming**--tumia mbinu zile zile za kuamua ikiwa unapaswa kuunda kitendaji kipya au object. Mbinu moja kama hiyo ni [kanuni ya uwajibikaji mmoja (single responsibility principle)](https://en.wikipedia.org/wiki/Single_responsibility_principle), yaani, kijenzi kinapaswa kufanya jambo moja tu. Ikiwa kitaishia kukua, inapaswa kigawanywe kiwe vijenzi vidogo.
* **CSS**--fikiria ni nini ungetengeneza viteule vya darasa. (Hatahivyo, vijenzi ni vidogo kwa kiasi fulani.)
* **Design**--fikiria jinsi unavyoweza kupanga safu za muundo.
-=======
-* **Programming**--use the same techniques for deciding if you should create a new function or object. One such technique is the [separation of concerns](https://en.wikipedia.org/wiki/Separation_of_concerns), that is, a component should ideally only be concerned with one thing. If it ends up growing, it should be decomposed into smaller subcomponents.
-* **CSS**--consider what you would make class selectors for. (However, components are a bit less granular.)
-* **Design**--consider how you would organize the design's layers.
->>>>>>> 8bb31acb86bf68fa33d97dd0f1b834dfa71e2b1a
Ikiwa JSON yako imeundwa vizuri, mara nyingi utapata kwamba inaelekeza kwa muundo wa vijenzi vya UI yako. Hiyo ni kwa sababu UI na miundo ya data mara nyingi huwa na usanifu sawa wa habari--yaani, umbo sawa. Tenganisha UI yako katika vijenzi, ambapo kila kijenzi kinalingana na kipande kimoja cha muundo yako wa data.
@@ -232,19 +226,10 @@ Kilichobaki labda ni hali.
Wacha tupitie moja baada ya nyingine tena:
-<<<<<<< HEAD
1. Orodha asili ya bidhaa **imepitishwa kama vifaa, kwa hivyo haijabainishwa.**
2. Maandishi ya utafutaji yanaonekana kuwa ya hali kwani yanabadilika kwa wakati na hayawezi kukokotwa kutoka kwa chochote.
3. Thamani ya kisanduku cha kuteua inaonekana kuwa hali kwani inabadilika kwa wakati na haiwezi kukokotwa kutoka kwa chochote.
4. Orodha iliyochujwa ya bidhaa **haijabainishwa kwa sababu inaweza kukokotwa** kwa kuchukua orodha asili ya bidhaa na kuichuja kulingana na maandishi ya utafutaji na thamani ya kisanduku cha kuteua.
-=======
-1. The original list of products is **passed in as props, so it's not state.**
-2. The search text seems to be state since it changes over time and can't be computed from anything.
-3. The value of the checkbox seems to be state since it changes over time and can't be computed from anything.
-4. The filtered list of products **isn't state because it can be computed** by taking the original list of products and filtering it according to the search text and value of the checkbox.
-
-This means only the search text and the value of the checkbox are state! Nicely done!
->>>>>>> 8bb31acb86bf68fa33d97dd0f1b834dfa71e2b1a
Hii ina maana kwamba ni maandishi ya utafutaji pekee na thamani ya kisanduku cha kuteua ndizo zilizotajwa! Imefanywa vizuri!
@@ -277,7 +262,6 @@ In the previous step, you found two pieces of state in this application: the sea
Katika hatua ya awali, ulipata vipande viwili vya hali katika programu hii: maandishi ya ingizo ya utafutaji, na thamani ya kisanduku cha kuteua. Katika mfano huu, daima huonekana pamoja, kwa hiyo ni mantiki kuviweka katika sehemu moja.
-<<<<<<< HEAD
Sasa wacha tupitie mkakati wetu kwao:
1. **Tambua vijenzi vinavyotumia hali:**
@@ -285,15 +269,6 @@ Sasa wacha tupitie mkakati wetu kwao:
* `SearchBar` inahitaji kuonyesha hali hiyo (maandishi ya utafutaji na thamani ya kisanduku cha kuteua).
1. **Tafuta mzazi wao wa kawaida:** Kijenzi mzazi cha kwanza ambacho vijenzi vyote viwili hushiriki ni `FilterableProductTable`.
2. **Amua mahali pa kuishi**: Tutaweka maandishi ya kichujio na thamani za hali zilizochaguliwa katika `FilterableProductTable`.
-=======
-1. **Identify components that use state:**
- * `ProductTable` needs to filter the product list based on that state (search text and checkbox value).
- * `SearchBar` needs to display that state (search text and checkbox value).
-2. **Find their common parent:** The first parent component both components share is `FilterableProductTable`.
-3. **Decide where the state lives**: We'll keep the filter text and checked state values in `FilterableProductTable`.
-
-So the state values will live in `FilterableProductTable`.
->>>>>>> 8bb31acb86bf68fa33d97dd0f1b834dfa71e2b1a
Kwa hivyo state thamani zitaishi katika `FilterableProductTable`.
@@ -481,16 +456,7 @@ function SearchBar({ filterText, inStockOnly }) {
Hata hivyo, bado hujaongeza msimbo wowote ili kujibu vitendo vya mtumiaji kama vile kuandika. Hii itakuwa hatua yako ya mwisho.
-<<<<<<< HEAD
## Hatua ya 5: Ongeza mtiririko wa data kinyume {/*step-5-add-inverse-data-flow*/}
-=======
-
-## Step 5: Add inverse data flow {/*step-5-add-inverse-data-flow*/}
-
-Currently your app renders correctly with props and state flowing down the hierarchy. But to change the state according to user input, you will need to support data flowing the other way: the form components deep in the hierarchy need to update the state in `FilterableProductTable`.
-
-React makes this data flow explicit, but it requires a little more typing than two-way data binding. If you try to type or check the box in the example above, you'll see that React ignores your input. This is intentional. By writing ``, you've set the `value` prop of the `input` to always be equal to the `filterText` state passed in from `FilterableProductTable`. Since `filterText` state is never set, the input never changes.
->>>>>>> 8bb31acb86bf68fa33d97dd0f1b834dfa71e2b1a
You want to make it so whenever the user changes the form inputs, the state updates to reflect those changes. The state is owned by `FilterableProductTable`, so only it can call `setFilterText` and `setInStockOnly`. To let `SearchBar` update the `FilterableProductTable`'s state, you need to pass these functions down to `SearchBar`:
diff --git a/src/content/learn/tutorial-tic-tac-toe.md b/src/content/learn/tutorial-tic-tac-toe.md
index ec8d0f61..e9634c3e 100644
--- a/src/content/learn/tutorial-tic-tac-toe.md
+++ b/src/content/learn/tutorial-tic-tac-toe.md
@@ -337,7 +337,11 @@ import './styles.css';
import App from './App';
```
+<<<<<<< HEAD
Mstari wa 1-5 unaleta vipande vyote muhimu pamoja:
+=======
+Lines 1-5 bring all the necessary pieces together:
+>>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61
* React
* Maktaba ya React ya kuwasiliana na kivinjari cha wavuti (React DOM)
@@ -551,7 +555,11 @@ export default function Board() {
}
```
+<<<<<<< HEAD
Angalia jinsi, kinyume na `div`s za kivinjari, viungo vyako `Board` na `Square` lazima vianze na herufi kubwa.
+=======
+Note how unlike the browser `div`s, your own components `Board` and `Square` must start with a capital letter.
+>>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61
Hebu tuangalie:
@@ -1094,7 +1102,11 @@ function Square({ value, onSquareClick }) {
}
```
+<<<<<<< HEAD
Sasa utaunganisha kipengele cha `onSquareClick` na function katika sehemu ya `Board` utakayoita `handleClick`. Ili kuunganisha `onSquareClick` na `handleClick`, utapita function kwa kipengele cha `onSquareClick` cha sehemu ya kwanza ya `Square`:
+=======
+Now you'll connect the `onSquareClick` prop to a function in the `Board` component that you'll name `handleClick`. To connect `onSquareClick` to `handleClick` you'll pass a function to the `onSquareClick` prop of the first `Square` component:
+>>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61
```js
export default function Board() {
@@ -2073,13 +2085,22 @@ export default function Game() {
}
```
+<<<<<<< HEAD
Unaweza kuona jinsi kanuni yako inavyopaswa kuonekana hapa chini. Kumbuka kwamba unapaswa kuona hitilafu katika koni ya zana za mende inayosema:
+=======
+You can see what your code should look like below. Note that you should see an error in the developer tools console that says:
+>>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61
Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of `Game`.
+<<<<<<< HEAD
Utarekebisha hitilafu hii katika sehemu inayofuata.
+=======
+
+You'll fix this error in the next section.
+>>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61
diff --git a/src/content/reference/react-dom/components/form.md b/src/content/reference/react-dom/components/form.md
index 1043b13a..10e9c679 100644
--- a/src/content/reference/react-dom/components/form.md
+++ b/src/content/reference/react-dom/components/form.md
@@ -48,9 +48,47 @@ To create interactive controls for submitting information, render the [built-in
## Usage {/*usage*/}
-### Handle form submission on the client {/*handle-form-submission-on-the-client*/}
+### Handle form submission with an event handler {/*handle-form-submission-with-an-event-handler*/}
-Pass a function to the `action` prop of form to run the function when the form is submitted. [`formData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) will be passed to the function as an argument so you can access the data submitted by the form. This differs from the conventional [HTML action](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#action), which only accepts URLs. After the `action` function succeeds, all uncontrolled field elements in the form are reset.
+Pass a function to the `onSubmit` event handler to run code when the form is submitted. By default, the browser sends the form data to the current URL and refreshes the page, so call [`e.preventDefault()`](https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault) to override that behavior.
+
+This example reads the submitted values with [`new FormData(e.target)`](https://developer.mozilla.org/en-US/docs/Web/API/FormData), which collects every field by its `name`. This keeps the inputs [uncontrolled](/reference/react-dom/components/input#reading-the-input-values-when-submitting-a-form). If you instead [control an input with state](/reference/react-dom/components/input#controlling-an-input-with-a-state-variable), read from that state on submit rather than from `FormData`.
+
+
+
+```js src/App.js
+export default function Search() {
+ function handleSubmit(e) {
+ // Prevent the browser from reloading the page
+ e.preventDefault();
+
+ // Read the form data
+ const form = e.target;
+ const formData = new FormData(form);
+ const query = formData.get("query");
+ alert(`You searched for '${query}'`);
+ }
+
+ return (
+
+ );
+}
+```
+
+
+
+
+
+Reading form data with `onSubmit` works in every version of React and gives you direct access to the [submit event](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit_event), so you can call `e.preventDefault()` and read the data yourself. Passing the function to the `action` prop instead runs the submission in a [Transition](/reference/react/useTransition). React then tracks the pending state, sends thrown errors to the nearest error boundary, and lets the form work with [`useActionState`](/reference/react/useActionState) and [`useOptimistic`](/reference/react/useOptimistic). An `action` can also be a [Server Function](/reference/rsc/server-functions), which `onSubmit` does not support.
+
+
+
+### Handle form submission with an action prop {/*handle-form-submission-with-an-action-prop*/}
+
+Pass a function to the `action` prop of form to run the function when the form is submitted. [`formData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) will be passed to the function as an argument so you can access the data submitted by the form. This differs from the conventional [HTML action](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#action), which only accepts URLs. Unlike `onSubmit`, an `action` runs in a [Transition](/reference/react/useTransition) and calling `e.preventDefault()` isn't needed. After the `action` function succeeds, all uncontrolled field elements in the form are reset.
diff --git a/src/content/reference/react/Component.md b/src/content/reference/react/Component.md
index 3b882f09..f6c8cc4b 100644
--- a/src/content/reference/react/Component.md
+++ b/src/content/reference/react/Component.md
@@ -1009,7 +1009,7 @@ Deriving state leads to verbose code and makes your components difficult to thin
#### Caveats {/*static-getderivedstatefromprops-caveats*/}
-- This method is fired on *every* render, regardless of the cause. This is different from [`UNSAFE_componentWillReceiveProps`](#unsafe_cmoponentwillreceiveprops), which only fires when the parent causes a re-render and not as a result of a local `setState`.
+- This method is fired on *every* render, regardless of the cause. This is different from [`UNSAFE_componentWillReceiveProps`](#unsafe_componentwillreceiveprops), which only fires when the parent causes a re-render and not as a result of a local `setState`.
- This method doesn't have access to the component instance. If you'd like, you can reuse some code between `static getDerivedStateFromProps` and the other class methods by extracting pure functions of the component props and state outside the class definition.
diff --git a/src/content/reference/react/use.md b/src/content/reference/react/use.md
index c13ad520..b20f723a 100644
--- a/src/content/reference/react/use.md
+++ b/src/content/reference/react/use.md
@@ -4,7 +4,7 @@ title: use
-`use` is a React API that lets you read the value of a resource like a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [context](/learn/passing-data-deeply-with-context).
+`use` is a React API that lets you read the value of a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [context](/learn/passing-data-deeply-with-context).
```js
const value = use(resource);
@@ -18,46 +18,73 @@ const value = use(resource);
## Reference {/*reference*/}
-### `use(resource)` {/*use*/}
+### `use(context)` {/*use-context*/}
-Call `use` in your component to read the value of a resource like a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [context](/learn/passing-data-deeply-with-context).
+Call `use` with a [context](/learn/passing-data-deeply-with-context) to read its value. Unlike [`useContext`](/reference/react/useContext), `use` can be called within loops and conditional statements like `if`.
-```jsx
+```js
import { use } from 'react';
-function MessageComponent({ messagePromise }) {
- const message = use(messagePromise);
+function Button() {
const theme = use(ThemeContext);
// ...
```
-Unlike React Hooks, `use` can be called within loops and conditional statements like `if`. Like React Hooks, the function that calls `use` must be a Component or Hook.
+[See more examples below.](#usage-context)
+
+#### Parameters {/*context-parameters*/}
-When called with a Promise, the `use` API integrates with [`Suspense`](/reference/react/Suspense) and [Error Boundaries](/reference/react/Component#catching-rendering-errors-with-an-error-boundary). The component calling `use` *suspends* while the Promise passed to `use` is pending. If the component that calls `use` is wrapped in a Suspense boundary, the fallback will be displayed. Once the Promise is resolved, the Suspense fallback is replaced by the rendered components using the data returned by the `use` API. If the Promise passed to `use` is rejected, the fallback of the nearest Error Boundary will be displayed.
+* `context`: A [context](/learn/passing-data-deeply-with-context) created with [`createContext`](/reference/react/createContext).
-[See more examples below.](#usage)
+#### Returns {/*context-returns*/}
-#### Parameters {/*parameters*/}
+The context value for the passed context, determined by the closest context provider above the calling component. If there is no provider, the returned value is the `defaultValue` passed to [`createContext`](/reference/react/createContext).
-* `resource`: this is the source of the data you want to read a value from. A resource can be a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or a [context](/learn/passing-data-deeply-with-context).
+#### Caveats {/*context-caveats*/}
-#### Returns {/*returns*/}
+* `use` must be called inside a Component or a Hook.
+* Reading context with `use` is not supported in [Server Components](/reference/rsc/server-components).
+
+---
-The `use` API returns the value that was read from the resource like the resolved value of a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [context](/learn/passing-data-deeply-with-context).
+### `use(promise)` {/*use-promise*/}
-#### Caveats {/*caveats*/}
+Call `use` with a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) to read its resolved value. The component calling `use` *suspends* while the Promise is pending. Despite its name, `use` is not a Hook. Unlike Hooks, it can be called inside loops and conditional statements like `if`.
-* The `use` API must be called inside a Component or a Hook.
-* When fetching data in a [Server Component](/reference/rsc/server-components), prefer `async` and `await` over `use`. `async` and `await` pick up rendering from the point where `await` was invoked, whereas `use` re-renders the component after the data is resolved.
-* Prefer creating Promises in [Server Components](/reference/rsc/server-components) and passing them to [Client Components](/reference/rsc/use-client) over creating Promises in Client Components. Promises created in Client Components are recreated on every render. Promises passed from a Server Component to a Client Component are stable across re-renders. [See this example](#streaming-data-from-server-to-client).
+```js
+import { use } from 'react';
+
+function MessageComponent({ messagePromise }) {
+ const message = use(messagePromise);
+ // ...
+```
+
+If the component that calls `use` is wrapped in a [Suspense](/reference/react/Suspense) boundary, the fallback will be displayed while the Promise is pending. Once the Promise is resolved, the Suspense fallback is replaced by the rendered components using the data returned by `use`. If the Promise is rejected, the fallback of the nearest [Error Boundary](/reference/react/Component#catching-rendering-errors-with-an-error-boundary) will be displayed.
+
+[See more examples below.](#usage-promises)
+
+#### Parameters {/*promise-parameters*/}
+
+* `promise`: A [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) whose resolved value you want to read. The Promise must be [cached](#caching-promises-for-client-components) so that the same instance is reused across re-renders.
+
+#### Returns {/*promise-returns*/}
+
+The resolved value of the Promise.
+
+#### Caveats {/*promise-caveats*/}
+
+* `use` must be called inside a Component or a Hook.
+* `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.
+* 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)
+* When passing a Promise from a Server Component to a Client Component, its resolved value must be [serializable](/reference/rsc/use-client#serializable-types).
---
-## Usage {/*usage*/}
+## Usage (Context) {/*usage-context*/}
### Reading context with `use` {/*reading-context-with-use*/}
-When a [context](/learn/passing-data-deeply-with-context) is passed to `use`, it works similarly to [`useContext`](/reference/react/useContext). While `useContext` must be called at the top level of your component, `use` can be called inside conditionals like `if` and loops like `for`. `use` is preferred over `useContext` because it is more flexible.
+When a [context](/learn/passing-data-deeply-with-context) is passed to `use`, it works similarly to [`useContext`](/reference/react/useContext). While `useContext` must be called at the top level of your component, `use` can be called inside conditionals like `if` and loops like `for`.
```js [[2, 4, "theme"], [1, 4, "ThemeContext"]]
import { use } from 'react';
@@ -194,11 +221,801 @@ function Button({ show, children }) {
-### Streaming data from the server to the client {/*streaming-data-from-server-to-client*/}
+### Reading a Promise from context {/*reading-a-promise-from-context*/}
+
+To share asynchronous data without prop drilling, set a Promise as a context value, then read it with `use(context)` and resolve it with `use(promise)`:
-Data can be streamed from the server to the client by passing a Promise as a prop from a Server Component to a Client Component.
+```js
+import { use } from 'react';
+import { UserContext } from './UserContext';
+
+function Profile() {
+ const userPromise = use(UserContext);
+ const user = use(userPromise);
+ return
{user.name}
;
+}
+```
+
+Reading the value requires two `use` calls because the context value itself isn't awaited. See [Before you use context](/learn/passing-data-deeply-with-context#before-you-use-context) for alternatives to consider before reaching for context.
+
+Wrap the components that read the Promise in a [Suspense](/reference/react/Suspense) boundary so only that subtree suspends while the Promise is pending. See [Usage (Promises)](#usage-promises) below for more on reading Promises with `use`.
+
+
+
+When this pattern is used with [Server Components](/reference/rsc/server-components), refetching the Promise requires refetching the Server Component that sets the Promise in context. Avoid setting the Promise in context high in the tree, since that would refetch large parts of the app unnecessarily.
+
+
+
+---
+
+## Usage (Promises) {/*usage-promises*/}
+
+### Reading a Promise with `use` {/*reading-a-promise-with-use*/}
+
+Call `use` with a Promise to read its resolved value. The component will [suspend](/reference/react/Suspense) while the Promise is pending.
+
+```js [[1, 4, "use(albumsPromise)"]]
+import { use } from 'react';
+
+function Albums({ albumsPromise }) {
+ const albums = use(albumsPromise);
+ return (
+
+ {albums.map(album => (
+
+ {album.title} ({album.year})
+
+ ))}
+
+ );
+}
+```
+
+Wrap the component that calls `use` in a [Suspense](/reference/react/Suspense) boundary so React can show a fallback while the Promise is pending. The closest Suspense boundary above the suspending component shows its fallback. Once the Promise resolves, React reads the value with `use` and replaces the fallback with the rendered component.
+
+
+
+#### Fetching data with `use` {/*fetching-data-with-use*/}
+
+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).
+
+
+
+```js src/App.js active
+import { use, Suspense } from 'react';
+import { ErrorBoundary } from 'react-error-boundary';
+import { fetchData } from './data.js';
+
+export default function App() {
+ return (
+ Could not fetch albums.
;
+}
+```
+
+```js src/data.js hidden
+// Note: the way you would do data fetching depends on
+// the framework that you use together with Suspense.
+// Normally, the caching logic would be inside a framework.
+
+let cache = new Map();
+
+export function fetchData(url) {
+ if (!cache.has(url)) {
+ cache.set(url, getData(url));
+ }
+ return cache.get(url);
+}
+
+async function getData(url) {
+ if (url === '/albums') {
+ return await getAlbums();
+ } else {
+ throw Error('Not implemented');
+ }
+}
+
+async function getAlbums() {
+ // Add a fake delay to make waiting noticeable.
+ await new Promise(resolve => {
+ setTimeout(resolve, 1000);
+ });
+
+ return [{
+ id: 13,
+ title: 'Let It Be',
+ year: 1970
+ }, {
+ id: 12,
+ title: 'Abbey Road',
+ year: 1969
+ }, {
+ id: 11,
+ title: 'Yellow Submarine',
+ year: 1969
+ }, {
+ id: 10,
+ title: 'The Beatles',
+ year: 1968
+ }];
+}
+```
+
+```json package.json hidden
+{
+ "dependencies": {
+ "react": "19.0.0",
+ "react-dom": "19.0.0",
+ "react-scripts": "^5.0.0",
+ "react-error-boundary": "4.0.3"
+ },
+ "main": "/index.js"
+}
+```
+
+
+
+
+
+#### Fetching data with `useEffect` {/*fetching-data-with-useeffect*/}
+
+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).
+
+
+
+```js src/App.js active
+import { useState, useEffect } from 'react';
+import { fetchAlbums } from './data.js';
+
+export default function App() {
+ const [albums, setAlbums] = useState(null);
+ const [isLoading, setIsLoading] = useState(true);
+ const [error, setError] = useState(null);
+
+ useEffect(() => {
+ fetchAlbums()
+ .then(data => {
+ setAlbums(data);
+ setIsLoading(false);
+ })
+ .catch(err => {
+ setError(err);
+ setIsLoading(false);
+ });
+ }, []);
+
+ if (isLoading) {
+ return
Loading...
;
+ }
+
+ if (error) {
+ return
Error: {error.message}
;
+ }
+
+ return (
+
+ {albums.map(album => (
+
+ {album.title} ({album.year})
+
+ ))}
+
+ );
+}
+```
-```js [[1, 4, "App"], [2, 2, "Message"], [3, 7, "Suspense"], [4, 8, "messagePromise", 30], [4, 5, "messagePromise"]]
+```js src/data.js hidden
+export async function fetchAlbums() {
+ // Add a fake delay to make waiting noticeable.
+ await new Promise(resolve => {
+ setTimeout(resolve, 1000);
+ });
+
+ return [{
+ id: 13,
+ title: 'Let It Be',
+ year: 1970
+ }, {
+ id: 12,
+ title: 'Abbey Road',
+ year: 1969
+ }, {
+ id: 11,
+ title: 'Yellow Submarine',
+ year: 1969
+ }, {
+ id: 10,
+ title: 'The Beatles',
+ year: 1968
+ }];
+}
+```
+
+
+
+
+
+
+
+
+
+##### Promises passed to `use` must be cached {/*promises-must-cached*/}
+
+Promises created during render are recreated on every render, which causes React to show the Suspense fallback repeatedly and prevents content from appearing.
+
+```js
+function Albums() {
+ // 🔴 `fetch` creates a new Promise on every render.
+ const albums = use(fetch('/albums'));
+ // ...
+}
+```
+
+Instead, pass a Promise from a cache, a Suspense-enabled framework, or a Server Component:
+
+```js
+// ✅ fetchData reads the Promise from a cache.
+const albums = use(fetchData('/albums'));
+```
+
+
+
+
+
+#### Why are Promises recreated on every render? {/*why-promises-recreated*/}
+
+[React doesn't preserve state for renders that suspended before mounting](/reference/react/Suspense#caveats). After each suspension, React retries rendering from scratch, so any Promise created during render is recreated.
+
+Common ways a Promise can be unintentionally recreated during render:
+
+```js
+function Albums() {
+ // 🔴 `fetch` creates a new Promise on every render.
+ const albums = use(fetch('/albums'));
+
+ // 🔴 Uncached `async` function calls create a new Promise on every render.
+ const albums = use((async () => {
+ const res = await fetch('/albums');
+ return res.json();
+ })());
+
+ // 🔴 Adding `.then` returns a new Promise on every render,
+ // even if `fetchData` is cached.
+ const albums = use(fetchData('/albums').then(res => res.json()));
+ // ...
+}
+```
+
+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.
+
+```js
+// ✅ fetchData reads the Promise from a cache.
+const albums = use(fetchData('/albums'));
+```
+
+
+
+---
+
+### Caching Promises for Client Components {/*caching-promises-for-client-components*/}
+
+Promises passed to `use` in Client Components must be cached so the same Promise instance is reused across re-renders. If a new Promise is created directly in render, React will display the Suspense fallback on every re-render.
+
+```js
+// ✅ Cache the Promise so the same one is reused across renders
+let cache = new Map();
+
+export function fetchData(url) {
+ if (!cache.has(url)) {
+ cache.set(url, getData(url));
+ }
+ return cache.get(url);
+}
+```
+
+The `fetchData` function returns the same Promise each time it's called with the same URL. When `use` receives the same Promise on a re-render, it reads the already-resolved value synchronously without suspending.
+
+
+
+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).
+
+
+
+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.
+
+
+
+```js src/App.js active
+import { use, Suspense, useState } from 'react';
+import { fetchData } from './data.js';
+
+export default function App() {
+ const [count, setCount] = useState(0);
+ return (
+ <>
+
+
+ );
+}
+```
+
+```js src/data.js hidden
+// Note: the way you would do data fetching depends on
+// the framework that you use together with Suspense.
+// Normally, the caching logic would be inside a framework.
+
+let cache = new Map();
+
+export function fetchData(url) {
+ if (!cache.has(url)) {
+ cache.set(url, getData(url));
+ }
+ return cache.get(url);
+}
+
+async function getData(url) {
+ if (url === '/albums') {
+ return await getAlbums();
+ } else {
+ throw Error('Not implemented');
+ }
+}
+
+async function getAlbums() {
+ // Add a fake delay to make waiting noticeable.
+ await new Promise(resolve => {
+ setTimeout(resolve, 1000);
+ });
+
+ return [{
+ id: 13,
+ title: 'Let It Be',
+ year: 1970
+ }, {
+ id: 12,
+ title: 'Abbey Road',
+ year: 1969
+ }, {
+ id: 11,
+ title: 'Yellow Submarine',
+ year: 1969
+ }];
+}
+```
+
+
+
+
+
+#### How to implement a promise cache {/*how-to-implement-a-promise-cache*/}
+
+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.
+
+```js
+let cache = new Map();
+
+function fetchData(url) {
+ if (!cache.has(url)) {
+ const promise = getData(url);
+ promise.status = 'pending';
+ promise.then(
+ value => {
+ promise.status = 'fulfilled';
+ promise.value = value;
+ },
+ reason => {
+ promise.status = 'rejected';
+ promise.reason = reason;
+ },
+ );
+ cache.set(url, promise);
+ }
+ return cache.get(url);
+}
+```
+
+This is primarily useful for library authors building Suspense-compatible data layers. React will set the `status` field itself on Promises that don't have it, but setting it yourself avoids an extra render when the data is already available.
+
+This cache pattern is the foundation for [re-fetching data](#re-fetching-data-in-client-components) (where changing the cache key triggers a new fetch) and [preloading data on hover](#preloading-data-on-hover) (where calling `fetchData` early means the Promise may already be resolved by the time `use` reads it).
+
+
+
+
+
+Don't skip calling `use` based on whether a Promise is already settled.
+
+Unlike other hooks, `use` can be called inside conditions and loops — but it must always be called for the Promise itself. Never read `promise.status` or `promise.value` directly to bypass `use`; always pass the Promise to `use` and let React handle it.
+
+
+```js
+// 🔴 Don't bypass `use` by reading promise status directly
+if (promise.status === 'fulfilled') {
+ return promise.value;
+}
+const value = use(promise);
+```
+
+```js
+// ✅ Pass the promise to `use` and let React track the promise
+const value = use(promise);
+```
+
+Bypassing `use` this way can break React Suspense optimizations and Suspense features for React DevTools. You can `use(promise)` conditionally, but don't conditionally `use(promise)` based on the promise itself.
+
+
+
+---
+
+### Re-fetching data in Client Components {/*re-fetching-data-in-client-components*/}
+
+To refresh data at the same URL (for example, with a "Refresh" button), invalidate the cache entry and start a new fetch inside a [`startTransition`](/reference/react/startTransition). Store the resulting Promise in state to trigger a re-render. While the new Promise is pending, React keeps showing the existing content because the update is inside a Transition.
+
+```js
+function App() {
+ const [albumsPromise, setAlbumsPromise] = useState(fetchData('/albums'));
+ const [isPending, startTransition] = useTransition();
+
+ function handleRefresh() {
+ startTransition(() => {
+ setAlbumsPromise(refetchData('/albums'));
+ });
+ }
+ // ...
+}
+```
+
+`refetchData` clears the old cache entry and starts a new fetch at the same URL. Storing the resulting Promise in state triggers a re-render inside the Transition. On re-render, `Albums` receives the new Promise and `use` suspends on it while React keeps showing the old content.
+
+
+
+```js src/App.js active
+import { Suspense, useState, useTransition } from 'react';
+import { use } from 'react';
+import { fetchData, refetchData } from './data.js';
+
+export default function App() {
+ const [albumsPromise, setAlbumsPromise] = useState(
+ () => fetchData('/the-beatles/albums')
+ );
+ const [isPending, startTransition] = useTransition();
+
+ function handleRefresh() {
+ startTransition(() => {
+ setAlbumsPromise(refetchData('/the-beatles/albums'));
+ });
+ }
+
+ return (
+ <>
+
+
;
+}
+```
+
+```js src/data.js hidden
+// Note: the way you would do data fetching depends on
+// the framework that you use together with Suspense.
+// Normally, the caching logic would be inside a framework.
+
+let cache = new Map();
+
+export function fetchData(url) {
+ if (!cache.has(url)) {
+ cache.set(url, getData(url));
+ }
+ return cache.get(url);
+}
+
+export function refetchData(url) {
+ cache.delete(url);
+ return fetchData(url);
+}
+
+async function getData(url) {
+ if (url.startsWith('/the-beatles/albums')) {
+ return await getAlbums();
+ } else {
+ throw Error('Not implemented');
+ }
+}
+
+async function getAlbums() {
+ // Add a fake delay to make waiting noticeable.
+ await new Promise(resolve => {
+ setTimeout(resolve, 1000);
+ });
+
+ return [{
+ id: 13,
+ title: 'Let It Be',
+ year: 1970
+ }, {
+ id: 12,
+ title: 'Abbey Road',
+ year: 1969
+ }, {
+ id: 11,
+ title: 'Yellow Submarine',
+ year: 1969
+ }, {
+ id: 10,
+ title: 'The Beatles',
+ year: 1968
+ }, {
+ id: 9,
+ title: 'Magical Mystery Tour',
+ year: 1967
+ }];
+}
+```
+
+```css
+button { margin-bottom: 10px; }
+```
+
+
+
+
+
+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.
+
+
+
+---
+
+### Preloading data on hover {/*preloading-data-on-hover*/}
+
+You can start loading data before it's needed by calling `fetchData` during a hover event. Since `fetchData` caches the Promise, the data may already be available by the time the user clicks. If the Promise has resolved by the time `use` reads it, React renders the component immediately without showing a Suspense fallback.
+
+```js
+