From b4610fbd4410371958587f2fdfd6c43d073cb918 Mon Sep 17 00:00:00 2001 From: Maken Cristhian <96421658+MakenRosa@users.noreply.github.com> Date: Mon, 22 Jun 2026 12:23:01 -0300 Subject: [PATCH 1/9] Clarify useLayoutEffect setup timing (#8488) --- src/content/reference/react/useLayoutEffect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/reference/react/useLayoutEffect.md b/src/content/reference/react/useLayoutEffect.md index 24b360404..79263b8e7 100644 --- a/src/content/reference/react/useLayoutEffect.md +++ b/src/content/reference/react/useLayoutEffect.md @@ -47,7 +47,7 @@ function Tooltip() { #### Parameters {/*parameters*/} -* `setup`: The function with your Effect's logic. Your setup function may also optionally return a *cleanup* function. Before your [component commits](/learn/render-and-commit#step-3-react-commits-changes-to-the-dom), React will run your setup function. After every commit with changed dependencies, React will first run the cleanup function (if you provided it) with the old values, and then run your setup function with the new values. Before your component is removed from the DOM, React will run your cleanup function. +* `setup`: The function with your Effect's logic. Your setup function may also optionally return a *cleanup* function. After your [component commits](/learn/render-and-commit#step-3-react-commits-changes-to-the-dom) to the DOM and before the browser repaints the screen, React will run your setup function. After every commit with changed dependencies, React will first run the cleanup function (if you provided it) with the old values, and then run your setup function with the new values. Before your component is removed from the DOM, React will run your cleanup function. * **optional** `dependencies`: The list of all reactive values referenced inside of the `setup` code. Reactive values include props, state, and all the variables and functions declared directly inside your component body. If your linter is [configured for React](/learn/editor-setup#linting), it will verify that every reactive value is correctly specified as a dependency. The list of dependencies must have a constant number of items and be written inline like `[dep1, dep2, dep3]`. React will compare each dependency with its previous value using the [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) comparison. If you omit this argument, your Effect will re-run after every commit of the component. From ecf6c2f191844815923add7ea551fb7b9ba76f6d Mon Sep 17 00:00:00 2001 From: Aurora Scharff <66901228+aurorascharff@users.noreply.github.com> Date: Wed, 24 Jun 2026 19:12:41 +0200 Subject: [PATCH 2/9] Increase dark-mode button contrast (#8494) Bumps button contrast to match the treatment on reactnative.dev. Dark mode: - primary text: dark:text-secondary (#404756) -> dark:text-gray-90 (#23272F) - secondary border: #404756 -> #4E5769 (matches RN's rgb(78,86,104)) Light mode: - secondary border: #D9DBE3 -> #BCC1CD (matches RN's rgb(188,193,205)) gray-90 keeps a subtle cyan tint on the teal button, per review feedback (gray-95 was too flat). --- src/components/ButtonLink.tsx | 2 +- tailwind.config.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/ButtonLink.tsx b/src/components/ButtonLink.tsx index bd98d5b38..dff09ed3a 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/tailwind.config.js b/tailwind.config.js index 9450cfa59..85d0e7050 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -46,8 +46,8 @@ module.exports = { 'inner-border-dark': 'inset 0 0 0 1px rgba(255, 255, 255, 0.08)', 'outer-border': '0 0 0 1px rgba(0, 0, 0, 0.1)', 'outer-border-dark': '0 0 0 1px rgba(255, 255, 255, 0.1)', - 'secondary-button-stroke': 'inset 0 0 0 1px #D9DBE3', - 'secondary-button-stroke-dark': 'inset 0 0 0 1px #404756', + 'secondary-button-stroke': 'inset 0 0 0 1px #BCC1CD', + 'secondary-button-stroke-dark': 'inset 0 0 0 1px #4E5769', none: 'none', }, extend: { From fb3854a4fc28a5ec853fb3bfdf40a60ed44a7c65 Mon Sep 17 00:00:00 2001 From: Ricky Date: Wed, 24 Jun 2026 16:31:14 -0400 Subject: [PATCH 3/9] Rewrite `use()` docs (#8305) * Claude use docs attempt * Human updates * Address review feedback * Address additional review feedback * Split Pitfall and DeepDive, clarify recreation examples * Reorder DeepDive: prose before correct example * Add Reading a Promise from context section * Address review feedback and align DeepDive with RSC docs style * Drop inaccurate claim about blocking page rendering * Address feedback * Address feedback: clarify use() accepts Promise or context * Apply suggestion from @rickhanlonii * Update src/content/reference/react/use.md Co-authored-by: Ricky * [use] Add Pitfall on refetching Promises from context in RSCs --------- Co-authored-by: Aurora Scharff Co-authored-by: Aurora Scharff <66901228+aurorascharff@users.noreply.github.com> --- src/content/reference/react/use.md | 1121 +++++++++++++++++++++++++--- 1 file changed, 997 insertions(+), 124 deletions(-) diff --git a/src/content/reference/react/use.md b/src/content/reference/react/use.md index c13ad5203..0fc152c7f 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,796 @@ 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.

}> + }> + + +
+ ); +} + +function Albums() { + const albums = use(fetchData('/albums')); + return ( +
    + {albums.map(album => ( +
  • + {album.title} ({album.year}) +
  • + ))} +
+ ); +} + +function Loading() { + return

Loading...

; +} +``` + +```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 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 ( + <> + +

Render count: {count}

+ Loading...

}> + +
+ + ); +} + +function Albums() { + const albums = use(fetchData('/albums')); + return ( +
    + {albums.map(album => ( +
  • + {album.title} ({album.year}) +
  • + ))} +
+ ); +} +``` + +```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 conditionally call `use` based on whether a Promise is settled. Always call `use` unconditionally and let React handle reading the `status` field. This ensures React DevTools can show that the component may suspend on data. + +```js +// 🔴 Don't conditionally skip `use` +if (promise.status === 'fulfilled') { + return promise.value; +} +const value = use(promise); +``` + +```js +// ✅ Always call `use` unconditionally +const value = use(promise); +``` -```js [[1, 4, "App"], [2, 2, "Message"], [3, 7, "Suspense"], [4, 8, "messagePromise", 30], [4, 5, "messagePromise"]] + + +--- + +### 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 ( + <> + +
+ }> + + +
+ + ); +} + +function Albums({ albumsPromise }) { + const albums = use(albumsPromise); + return ( +
    + {albums.map(album => ( +
  • + {album.title} ({album.year}) +
  • + ))} +
+ ); +} + +function Loading() { + return

Loading...

; +} +``` + +```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 + + ))} + + }> + + + + ); +} + +function Loading() { + return

Loading...

; +} +``` + +```js src/Albums.js +import { use } from 'react'; +import { fetchData } from './data.js'; + +export default function Albums({ artistId }) { + const albums = use(fetchData(`/${artistId}/albums`)); + return ( +
    + {albums.map(album => ( +
  • + {album.title} ({album.year}) +
  • + ))} +
+ ); +} +``` + +```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)) { + const promise = getData(url); + // Set status fields so React can read the value + // synchronously if the Promise resolves before + // `use` is called (e.g. when preloading on hover). + 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); +} + +async function getData(url) { + if (url.startsWith('/the-beatles/albums')) { + return await getAlbums('the-beatles'); + } else if (url.startsWith('/led-zeppelin/albums')) { + return await getAlbums('led-zeppelin'); + } else if (url.startsWith('/pink-floyd/albums')) { + return await getAlbums('pink-floyd'); + } else { + throw Error('Not implemented'); + } +} + +async function getAlbums(artistId) { + // Add a fake delay to make waiting noticeable. + await new Promise(resolve => { + setTimeout(resolve, 800); + }); + + if (artistId === 'the-beatles') { + return [{ + id: 13, + title: 'Let It Be', + year: 1970 + }, { + id: 12, + title: 'Abbey Road', + year: 1969 + }, { + id: 11, + title: 'Yellow Submarine', + year: 1969 + }]; + } else if (artistId === 'led-zeppelin') { + return [{ + id: 10, + title: 'Coda', + year: 1982 + }, { + id: 9, + title: 'In Through the Out Door', + year: 1979 + }, { + id: 8, + title: 'Presence', + year: 1976 + }]; + } else { + return [{ + id: 7, + title: 'The Wall', + year: 1979 + }, { + id: 6, + title: 'Animals', + year: 1977 + }, { + id: 5, + title: 'Wish You Were Here', + year: 1975 + }]; + } +} +``` + +```css +button { margin-right: 10px; } +``` + + + +--- + +### Streaming data from server to client {/*streaming-data-from-server-to-client*/} + +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 { fetchMessage } from './lib.js'; import { Message } from './message.js'; @@ -212,9 +1024,9 @@ export default function App() { } ``` -The Client Component then takes the Promise it received as a prop and passes it to the `use` API. This allows the Client Component to read the value from the Promise that was initially created by the Server Component. +The Client Component then takes the Promise it received as a prop and passes it to the `use` API. This allows the Client Component to read the value from the Promise that was initially created by the Server Component. -```js [[2, 6, "Message"], [4, 6, "messagePromise"], [4, 7, "messagePromise"], [5, 7, "use"]] +```js // message.js 'use client'; @@ -225,7 +1037,7 @@ export function Message({ messagePromise }) { return

Here is the message: {messageContent}

; } ``` -Because `Message` is wrapped in [`Suspense`](/reference/react/Suspense), the fallback will be displayed until the Promise is resolved. When the Promise is resolved, the value will be read by the `use` API and the `Message` component will replace the Suspense fallback. +Because `Message` is wrapped in a [Suspense](/reference/react/Suspense) boundary, the fallback will be displayed until the Promise is resolved. When the Promise is resolved, the value will be read by the `use` API and the `Message` component will replace the Suspense fallback. @@ -292,109 +1104,161 @@ root.render( - - -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. - - - - #### Should I resolve a Promise in a Server or Client Component? {/*resolve-promise-in-server-or-client-component*/} -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. +A Promise can be resolved with `await` in a Server Component, or passed as a prop to a Client Component and resolved there with `use`. + +Using `await` in a Server Component suspends the Server Component itself, and the Client Component receives the resolved value as a prop: ```js +// Server Component export default async function App() { + // Will suspend the Server Component. const messageContent = await fetchMessage(); - return + return ; } ``` -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. +A Server Component can also start a Promise without awaiting it and pass the Promise to a Client Component. The Server Component returns immediately, and the Client Component suspends when it calls `use`: - +```js +// Server Component +export default function App() { + // Not awaited: starts here, resolves on the client. + const messagePromise = fetchMessage(); + return ; +} +``` -### Dealing with rejected Promises {/*dealing-with-rejected-promises*/} +```js +// Client Component +'use client'; +import { use } from 'react'; -In some cases a Promise passed to `use` could be rejected. You can handle rejected Promises by either: +export function Message({ messagePromise }) { + // Will suspend until the data is available. + const messageContent = use(messagePromise); + return

{messageContent}

; +} +``` -1. [Displaying an error to users with an Error Boundary.](#displaying-an-error-to-users-with-error-boundary) -2. [Providing an alternative value with `Promise.catch`](#providing-an-alternative-value-with-promise-catch) +Prefer `await` in a Server Component when possible, since it keeps the data fetching on the server. If a Server Component above already awaits the data, pass the resolved value down as a prop instead of creating a new Promise to call `use`. - -`use` cannot be called in a try-catch block. Instead of a try-catch block [wrap your component in an Error Boundary](#displaying-an-error-to-users-with-error-boundary), or [provide an alternative value to use with the Promise's `.catch` method](#providing-an-alternative-value-with-promise-catch). - +You can also pass promise as a prop to a Client Component without awaiting it, and then read it with `use(promise)` to suspend deeper in the tree. This allows more of the surrounding UI to complete while the Promise is pending. A common case is interactive content like popovers and tooltips, where the data is needed only after a hover or click. Client Components can't `await`, so they rely on `use` to suspend on a Promise. -#### Displaying an error to users with an Error Boundary {/*displaying-an-error-to-users-with-error-boundary*/} +In either case, wrap the component that reads the Promise in a Suspense boundary so React can show a fallback while the Promise is pending. See [Revealing content together at once](/reference/react/Suspense#revealing-content-together-at-once) for guidance on boundary placement. -If you'd like to display an error to your users when a Promise is rejected, you can use an [Error Boundary](/reference/react/Component#catching-rendering-errors-with-an-error-boundary). To use an Error Boundary, wrap the component where you are calling the `use` API in an Error Boundary. If the Promise passed to `use` is rejected the fallback for the Error Boundary will be displayed. + - +--- -```js src/message.js active -"use client"; +### Displaying an error with an Error Boundary {/*displaying-an-error-with-an-error-boundary*/} -import { use, Suspense } from "react"; +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. + +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. + + + +```js src/App.js active +import { use, Suspense, useState, startTransition } from "react"; import { ErrorBoundary } from "react-error-boundary"; +import { fetchData, refetchData } from "./data.js"; + +export default function App() { + const [albumsPromise, setAlbumsPromise] = useState( + () => fetchData('/the-beatles/albums') + ); + + function handleRetry() { + startTransition(() => { + setAlbumsPromise(refetchData('/the-beatles/albums')); + }); + } -export function MessageContainer({ messagePromise }) { return ( - ⚠️Something went wrong

}> - ⌛Downloading message...

}> - + ( + <> +

⚠️ Something went wrong loading the albums.

+ + + )} + > + Loading...

}> +
); } -function Message({ messagePromise }) { - const content = use(messagePromise); - return

Here is the message: {content}

; +function Albums({ albumsPromise }) { + const albums = use(albumsPromise); + return ( +
    + {albums.map(album => ( +
  • + {album.title} ({album.year}) +
  • + ))} +
+ ); } ``` -```js src/App.js hidden -import { useState } from "react"; -import { MessageContainer } from "./message.js"; - -function fetchMessage() { - return new Promise((resolve, reject) => setTimeout(reject, 1000)); -} +```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. -export default function App() { - const [messagePromise, setMessagePromise] = useState(null); - const [show, setShow] = useState(false); - function download() { - setMessagePromise(fetchMessage()); - setShow(true); - } +let cache = new Map(); +let retried = false; - if (show) { - return ; - } else { - return ; +export function fetchData(url) { + if (!cache.has(url)) { + cache.set(url, getData(url)); } + return cache.get(url); } -``` - -```js src/index.js hidden -import React, { StrictMode } from 'react'; -import { createRoot } from 'react-dom/client'; -import './styles.css'; -// TODO: update this example to use -// the Codesandbox Server Component -// demo environment once it is created -import App from './App'; +export function refetchData(url) { + cache.delete(url); + retried = true; + return fetchData(url); +} -const root = createRoot(document.getElementById('root')); -root.render( - - - -); +async function getData(url) { + // Add a fake delay to make the loading state visible. + await new Promise(resolve => setTimeout(resolve, 1000)); + if (url === '/the-beatles/albums') { + // Fail the first attempt to demonstrate the Error Boundary, + // then succeed on retry. + if (!retried) { + throw new Error('Example Error: Failed to fetch albums'); + } + 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 + }]; + } + throw new Error('Not implemented'); +} ``` ```json package.json hidden @@ -410,53 +1274,62 @@ root.render( ```
-#### Providing an alternative value with `Promise.catch` {/*providing-an-alternative-value-with-promise-catch*/} +--- -If you'd like to provide an alternative value when the Promise passed to `use` is rejected you can use the Promise's [`catch`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch) method. +## Troubleshooting {/*troubleshooting*/} -```js [[1, 6, "catch"],[2, 7, "return"]] -import { Message } from './message.js'; +### I'm getting an error: "Suspense Exception: This is not a real error!" {/*suspense-exception-error*/} -export default function App() { - const messagePromise = new Promise((resolve, reject) => { - reject(); - }).catch(() => { - return "no new message found."; - }); +You are calling `use` inside a try-catch block. `use` throws internally to integrate with Suspense, so it cannot be wrapped in try-catch. Instead, wrap the component that calls `use` in an [Error Boundary](#displaying-an-error-with-an-error-boundary) to handle errors. - return ( - waiting for message...

}> - -
- ); -} +```jsx +function Albums({ albumsPromise }) { + try { + // ❌ Don't wrap `use` in try-catch + const albums = use(albumsPromise); + } catch (e) { + return

Error

; + } + // ... ``` -To use the Promise's `catch` method, call `catch` on the Promise object. `catch` takes a single argument: a function that takes an error message as an argument. Whatever is returned by the function passed to `catch` will be used as the resolved value of the Promise. +Instead, wrap the component in an Error Boundary: ---- +```jsx +function Albums({ albumsPromise }) { + // ✅ Call `use` without try-catch + const albums = use(albumsPromise); + // ... +``` -## Troubleshooting {/*troubleshooting*/} +```jsx +// ✅ Use an Error Boundary to handle errors +Error

}> + +
+``` -### "Suspense Exception: This is not a real error!" {/*suspense-exception-error*/} +--- -You are either calling `use` outside of a React Component or Hook function, or calling `use` in a try–catch block. If you are calling `use` inside a try–catch block, wrap your component in an Error Boundary, or call the Promise's `catch` to catch the error and resolve the Promise with another value. [See these examples](#dealing-with-rejected-promises). +### I'm getting a warning: "A component was suspended by an uncached promise" {/*uncached-promise-error*/} -If you are calling `use` outside a React Component or Hook function, move the `use` call to a React Component or Hook function. +The Promise passed to `use` is not cached, so React cannot reuse it across re-renders. -```jsx -function MessageComponent({messagePromise}) { - function download() { - // ❌ the function calling `use` is not a Component or Hook - const message = use(messagePromise); - // ... +This commonly happens when calling `fetch` or an `async` function directly in render: + +```js +function Albums() { + // 🔴 This creates a new Promise on every render + const albums = use(fetch('/albums')); + // ... +} ``` -Instead, call `use` outside any component closures, where the function that calls `use` is a Component or Hook. +To fix this, cache the Promise so the same instance is reused: -```jsx -function MessageComponent({messagePromise}) { - // ✅ `use` is being called from a component. - const message = use(messagePromise); - // ... +```js +// ✅ fetchData returns the same Promise for the same URL +const albums = use(fetchData('/albums')); ``` + +See [caching Promises for Client Components](#caching-promises-for-client-components) for more details. From b6e9b3c44da5f02d016b218da239dd466df7ac14 Mon Sep 17 00:00:00 2001 From: Aurora Scharff Date: Wed, 24 Jun 2026 22:39:15 +0200 Subject: [PATCH 4/9] [form] Document onSubmit event handler alongside action --- .../reference/react-dom/components/form.md | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/src/content/reference/react-dom/components/form.md b/src/content/reference/react-dom/components/form.md index 1043b13a0..9c078aa02 100644 --- a/src/content/reference/react-dom/components/form.md +++ b/src/content/reference/react-dom/components/form.md @@ -48,9 +48,44 @@ 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. Read the submitted data with [`new FormData(e.target)`](https://developer.mozilla.org/en-US/docs/Web/API/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 formData = new FormData(e.target); + 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). The `action` prop, described next, builds on this with extra features like automatic form resets, pending states with [`useFormStatus`](/reference/react-dom/hooks/useFormStatus), and [Server Functions](/reference/rsc/server-functions). + + + +### Handle form submission with an action {/*handle-form-submission-with-an-action*/} + +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. From 1f48fb46a8d1d3b4c8758f18a7aec55323152242 Mon Sep 17 00:00:00 2001 From: Aurora Scharff Date: Wed, 24 Jun 2026 22:50:49 +0200 Subject: [PATCH 5/9] [form] Refine onSubmit/action framing and address review --- src/content/reference/react-dom/components/form.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/content/reference/react-dom/components/form.md b/src/content/reference/react-dom/components/form.md index 9c078aa02..10e9c6794 100644 --- a/src/content/reference/react-dom/components/form.md +++ b/src/content/reference/react-dom/components/form.md @@ -50,7 +50,9 @@ To create interactive controls for submitting information, render the [built-in ### Handle form submission with an event handler {/*handle-form-submission-with-an-event-handler*/} -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. Read the submitted data with [`new FormData(e.target)`](https://developer.mozilla.org/en-US/docs/Web/API/FormData). +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`. @@ -61,7 +63,8 @@ export default function Search() { e.preventDefault(); // Read the form data - const formData = new FormData(e.target); + const form = e.target; + const formData = new FormData(form); const query = formData.get("query"); alert(`You searched for '${query}'`); } @@ -79,11 +82,11 @@ export default function Search() { -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). The `action` prop, described next, builds on this with extra features like automatic form resets, pending states with [`useFormStatus`](/reference/react-dom/hooks/useFormStatus), and [Server Functions](/reference/rsc/server-functions). +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 {/*handle-form-submission-with-an-action*/} +### 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. From 93f6c2773c368a22d0b84e2e585628838edb4bd2 Mon Sep 17 00:00:00 2001 From: MaxwellCohen Date: Thu, 25 Jun 2026 01:34:12 -0500 Subject: [PATCH 6/9] fix: update use.md pitfall to make conditional calling clearer (#8499) * fix: update use.md pitfall to mention that bypassing use can corrupt React's internal state tracking * Apply suggestion from @rickhanlonii * Apply suggestion from @rickhanlonii * Apply suggestion from @rickhanlonii * Apply suggestion from @rickhanlonii * Update use.md with caution on bypassing `use` Add warning about bypassing `use` and its effects on React Suspense. * Apply suggestion from @rickhanlonii * Update guidance on using the `use` hook with Promises Clarify usage of `use` hook regarding Promise handling. * Clarify usage of `use` with Promises --------- Co-authored-by: Ricky --- src/content/reference/react/use.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/content/reference/react/use.md b/src/content/reference/react/use.md index 0fc152c7f..1780f82e7 100644 --- a/src/content/reference/react/use.md +++ b/src/content/reference/react/use.md @@ -662,10 +662,13 @@ This cache pattern is the foundation for [re-fetching data](#re-fetching-data-in -Don't conditionally call `use` based on whether a Promise is settled. Always call `use` unconditionally and let React handle reading the `status` field. This ensures React DevTools can show that the component may suspend on data. +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 conditionally skip `use` +// 🔴 Don't bypass `use` by reading promise status directly if (promise.status === 'fulfilled') { return promise.value; } @@ -673,10 +676,12 @@ const value = use(promise); ``` ```js -// ✅ Always call `use` unconditionally +// ✅ 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. + --- From 12181aeb86178f07d4bb8fa24448cc855dc21504 Mon Sep 17 00:00:00 2001 From: Srijan Dubey <87586713+Srijan-D@users.noreply.github.com> Date: Sun, 28 Jun 2026 03:59:47 +0530 Subject: [PATCH 7/9] Fix broken internal link in Component reference (anchor) (#8344) * Fix broken internal link in Component reference (anchor) * chore: trigger CLA check --- src/content/reference/react/Component.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/reference/react/Component.md b/src/content/reference/react/Component.md index 3b882f097..f6c8cc4bf 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. From 152a471aa9ac2f6f0f3e64c04f39da790d40cf61 Mon Sep 17 00:00:00 2001 From: Jihwan Date: Sun, 28 Jun 2026 07:31:05 +0900 Subject: [PATCH 8/9] Fix incorrect links on versions page (#8461) --- src/content/versions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/versions.md b/src/content/versions.md index 62be00cc3..b48dc364c 100644 --- a/src/content/versions.md +++ b/src/content/versions.md @@ -286,7 +286,7 @@ For versions older than React 15, see [15.react.dev](https://15.react.dev). - [React v0.4.0](https://legacy.reactjs.org/blog/2013/07/17/react-v0-4-0.html) - [New in React v0.4: Prop Validation and Default Values](https://legacy.reactjs.org/blog/2013/07/11/react-v0-4-prop-validation-and-default-values.html) - [New in React v0.4: Autobind by Default](https://legacy.reactjs.org/blog/2013/07/02/react-v0-4-autobind-by-default.html) -- [React v0.3.3](https://legacy.reactjs.org/blog/2013/07/02/react-v0-4-autobind-by-default.html) +- [React v0.3.3](https://legacy.reactjs.org/blog/2013/06/21/react-v0-3-3.html) **Releases** - [v0.10.0 (March 2014)](https://github.com/facebook/react/blob/main/CHANGELOG.md#0100-march-21-2014) @@ -300,7 +300,7 @@ For versions older than React 15, see [15.react.dev](https://15.react.dev). - [v0.3.3 (June 2013)](https://github.com/facebook/react/blob/main/CHANGELOG.md#033-june-20-2013) - [v0.3.2 (May 2013)](https://github.com/facebook/react/blob/main/CHANGELOG.md#032-may-31-2013) - [v0.3.1 (May 2013)](https://github.com/facebook/react/blob/main/CHANGELOG.md#031-may-30-2013) -- [v0.3.0 (May 2013)](https://github.com/facebook/react/blob/main/CHANGELOG.md#031-may-30-2013) +- [v0.3.0 (May 2013)](https://github.com/facebook/react/blob/main/CHANGELOG.md#030-may-29-2013) ### Initial Commit {/*initial-commit*/} From a27ed5b698bb7ff13657655698defa91b15bf077 Mon Sep 17 00:00:00 2001 From: anilcanboga Date: Tue, 28 Jul 2026 23:36:41 +0300 Subject: [PATCH 9/9] sync-152a471a --- src/content/reference/react/Component.md | 6 +- src/content/reference/react/Fragment.md | 75 +---- src/content/reference/react/use.md | 273 +++--------------- .../reference/react/useLayoutEffect.md | 6 +- 4 files changed, 55 insertions(+), 305 deletions(-) diff --git a/src/content/reference/react/Component.md b/src/content/reference/react/Component.md index 9f302f992..5c57199ff 100644 --- a/src/content/reference/react/Component.md +++ b/src/content/reference/react/Component.md @@ -1009,11 +1009,7 @@ State türetmek ayrıntılı koda yol açar ve bileşenlerinizi düşünmeyi zor #### Uyarılar {/*static-getderivedstatefromprops-caveats*/} -<<<<<<< HEAD -- Bu metod, nedeni ne olursa olsun *her* renderlamada tetiklenir. Bu, yalnızca üst bileşenin yeniden renderlamaya neden olduğunda tetiklenen ve yerel `setState` sonucu olarak tetiklenmeyen [`UNSAFE_componentWillReceiveProps`](#unsafe_cmoponentwillreceiveprops)'tan farklıdır. -======= -- 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`. ->>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61 +- Bu method, nedeni ne olursa olsun *her* render’da tetiklenir. Bu, yalnızca parent bir re-render’a neden olduğunda tetiklenen ve local `setState` sonucu tetiklenmeyen [`UNSAFE_componentWillReceiveProps`](#unsafe_componentwillreceiveprops)’tan farklıdır. - Bu metod, bileşen örneğine erişime sahip değildir. İsterseniz, `static getDerivedStateFromProps` ve diğer sınıf metodları arasında, bileşen prop'larının ve state'inin saf fonksiyonlarını sınıf tanımının dışında çıkararak bazı kodları yeniden kullanabilirsiniz. diff --git a/src/content/reference/react/Fragment.md b/src/content/reference/react/Fragment.md index 92ba1e27f..2407a1c59 100644 --- a/src/content/reference/react/Fragment.md +++ b/src/content/reference/react/Fragment.md @@ -6,11 +6,7 @@ title: (<>...) ``, genellikle `<>...` syntax’ı ile kullanılır ve element’leri bir wrapper node olmadan gruplamanızı sağlar. -<<<<<<< HEAD - Fragment'ler ayrıca ref'leri de kabul edebilir, bu da sarmalayıcı öğe eklemeden alt DOM düğümleriyle etkileşimde bulunmanı sağlar. Aşağıda referans ve kullanım örneklerini görebilirsin. -======= -Fragments can also accept refs, which enable interacting with underlying DOM nodes without adding wrapper elements. ->>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61 +Fragment’lar ayrıca ref kabul edebilir; bu da wrapper element eklemeden underlying DOM node’larıyla etkileşim kurmayı sağlar. ```js <> @@ -33,59 +29,22 @@ Tek bir elemana ihtiyaç duyduğunuz durumlarda, elemanları `` içine #### Prop'lar {/*props*/} -<<<<<<< HEAD -- **optional** `key`: Açık `` sözdizimi ile tanımlanan Fragment'ler [key] alabilir. (/learn/rendering-lists#keeping-list-items-in-order-with-key) -- **optional** `ref`: Bir ref objesi (örneğin [`useRef`](/reference/react/useRef) ile oluşturulmuş) veya [callback function](/reference/react-dom/components/common#ref-callback). React, Fragment tarafından sarılan DOM düğümleriyle etkileşim kurmak için yöntemler içeren bir `FragmentInstance`'ı ref değeri olarak sağlar. - -### FragmentInstance {/*fragmentinstance*/} - -Fragment'e bir ref verdiğinde, React Fragment tarafından sarılan DOM düğümleriyle etkileşim için yöntemler içeren bir `FragmentInstance` nesnesi sağlar: - -**Olay yönetimi yöntemleri:** -- `addEventListener(type, listener, options?)`: Fragment'in tüm birinci seviyedeki DOM çocuklarına bir olay dinleyici ekler. -- `removeEventListener(type, listener, options?)`: Fragment'in tüm birinci seviyedeki DOM çocuklarından bir olay dinleyici kaldırır. -- `dispatchEvent(event)`: Fragment'in sanal bir çocuğuna bir olay gönderir; eklenen dinleyicileri çağırır ve DOM üstüne kabarcık yapabilir. - -**Layout method’ları:** -- `compareDocumentPosition(otherNode)`: Fragment’in document position’ını başka bir node ile karşılaştırır. - - Fragment’in children’ları varsa, native `compareDocumentPosition` value’su return edilir. - - Empty Fragment’ler, React tree içindeki positioning’i karşılaştırmayı dener ve `Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC` içerir. - - Portaling veya diğer insertion’lar nedeniyle React tree ve DOM tree içinde farklı relationship’e sahip element’ler `Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC` olur. -- `getClientRects()`: Tüm children’ların bounding rectangle’larını temsil eden `DOMRect` object’lerinden oluşan flat bir array return eder. -- `getRootNode()`: Fragment’in parent DOM node’unu içeren root node’u return eder. - -**Odak (focus) yönetimi yöntemleri:** -- `focus(options?)`: Fragment'teki ilk odaklanabilir DOM düğümünü odaklar. Odak derinlemesine, çocuklar üzerinde denenir. -- `focusLast(options?)`: Fragment'teki son odaklanabilir DOM düğümünü odaklar. Odak derinlemesine, çocuklar üzerinde denenir. -- `blur()`: Eğer `document.activeElement` Fragment içindeyse odak kaldırılır. - -**Gözlemleme (observer) yöntemleri:** -- `observeUsing(observer)`: Fragment'in DOM çocuklarını bir `IntersectionObserver` veya `ResizeObserver` ile gözlemlemeye başlar. -- `unobserveUsing(observer)`: Belirtilen observer ile Fragment'in DOM çocuklarını gözlemlemeyi durdurur. -======= -- **optional** `key`: Fragments declared with the explicit `` syntax may have [keys.](/learn/rendering-lists#keeping-list-items-in-order-with-key) -- **optional** `ref`: A ref object (e.g. from [`useRef`](/reference/react/useRef)) or [callback function](/reference/react-dom/components/common#ref-callback). React provides a `FragmentInstance` as the ref value that implements methods for interacting with the DOM nodes wrapped by the Fragment. ->>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61 +- **optional** `key`: Açık `` syntax’iyle tanımlanan Fragment’lar [key’lere](/learn/rendering-lists#keeping-list-items-in-order-with-key) sahip olabilir. +- **optional** `ref`: Bir ref object’i (örn. [`useRef`](/reference/react/useRef)’ten gelen) veya [callback function](/reference/react-dom/components/common#ref-callback). React, ref value olarak Fragment tarafından sarılan DOM node’larıyla etkileşim kurmak için method’lar implemente eden bir `FragmentInstance` sağlar. #### Uyarılar {/*caveats*/} -<<<<<<< HEAD -- Eğer bir Fragment'a key değeri geçirmek istiyorsanız, <>... sözdizimini kullanamazsınız. 'React'ten Fragment'ı içe aktarmanız ve `...` şeklinde render etmeniz gerekmektedir. - -- React, `<>`'dan `[]`'a veya geriye dönerken, ya da `<>`'dan ``'a ve geriye dönerken [state sıfırlamaz](/learn/preserving-and-resetting-state). Bu durum yalnızca tek seviye derinlikte çalışır: örneğin, `<><>`'dan ``'a geçmek durumu sıfırlar. Kesin anlamları [burada](https://gist.github.com/clemmy/b3ef00f9507909429d8aa0d3ee4f986b) görebilirsiniz. -======= -* If you want to pass `key` to a Fragment, you can't use the `<>...` syntax. You have to explicitly import `Fragment` from `'react'` and render `...`. +* Bir Fragment’a `key` geçirmek istiyorsanız, `<>...` syntax’ini kullanamazsınız. `'react'` içinden `Fragment`’ı açıkça import etmeniz ve `...` şeklinde render etmeniz gerekir. -* React does not [reset state](/learn/preserving-and-resetting-state) when you go from rendering `<>` to `[]` or back, or when you go from rendering `<>` to `` and back. This only works a single level deep: for example, going from `<><>` to `` resets the state. See the precise semantics [here.](https://gist.github.com/clemmy/b3ef00f9507909429d8aa0d3ee4f986b) ->>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61 +* React, `<>` render etmekten `[]` render etmeye geçtiğinizde veya geri döndüğünüzde ya da `<>` render etmekten `` render etmeye geçtiğinizde ve geri döndüğünüzde [state’i resetlemez](/learn/preserving-and-resetting-state). Bu yalnızca tek bir seviye derinlikte çalışır: örneğin, `<><>` yapısından `` yapısına geçmek state’i resetler. Kesin semantiklere [buradan](https://gist.github.com/clemmy/b3ef00f9507909429d8aa0d3ee4f986b) bakabilirsiniz. -* If you want to pass `ref` to a Fragment, you can't use the `<>...` syntax. You have to explicitly import `Fragment` from `'react'` and render `...`. +* Bir Fragment’a `ref` geçirmek istiyorsanız, `<>...` syntax’ini kullanamazsınız. `'react'` içinden `Fragment`’ı açıkça import etmeniz ve `...` şeklinde render etmeniz gerekir. --- ### `FragmentInstance` {/*fragmentinstance*/} -When you pass a `ref` to a Fragment, React provides a `FragmentInstance` object. It implements methods for interacting with the first-level DOM children wrapped by the Fragment. +Bir Fragment’a `ref` geçirdiğinizde, React bir `FragmentInstance` object’i sağlar. Bu object, Fragment tarafından sarılan birinci seviye DOM child’larıyla etkileşim kurmak için method’lar implemente eder. * [`addEventListener`](#addeventlistener) and [`removeEventListener`](#removeeventlistener) manage event listeners across all first-level DOM children. * [`dispatchEvent`](#dispatchevent) dispatches an event on the Fragment, which can bubble to the DOM parent. @@ -502,17 +461,11 @@ function PostBody({ body }) { --- -<<<<<<< HEAD -### Fragment ref'lerini DOM etkileşimi için kullanma {/*using-fragment-refs-for-dom-interaction*/} +### Wrapper element olmadan event listener ekleme {/*adding-event-listeners-without-wrapper*/} -Fragment ref'leri, ekstra sarmalayıcı öğe eklemeden Fragment tarafından sarılan DOM düğümleriyle etkileşimde bulunmanı sağlar. Bu, olay yönetimi, görünürlük takibi, odak yönetimi ve `ReactDOM.findDOMNode()` gibi kullanım dışı kalmış desenlerin yerine geçmek için faydalıdır. -======= -### Adding event listeners without a wrapper element {/*adding-event-listeners-without-wrapper*/} - -Fragment `ref`s let you add event listeners to a group of elements without adding a wrapper DOM node. Use a [ref callback](/reference/react-dom/components/common#ref-callback) to attach and clean up listeners: +Fragment `ref`leri, wrapper DOM node’u eklemeden bir grup elemente event listener eklemenizi sağlar. Listener’ları attach etmek ve cleanup yapmak için bir [ref callback](/reference/react-dom/components/common#ref-callback) kullanın: ->>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61 ```js import { Fragment, useState, useRef, useEffect } from 'react'; @@ -597,15 +550,9 @@ Methods like `addEventListener`, `observeUsing`, and `getClientRects` operate on --- -<<<<<<< HEAD -### Fragment ref'leri ile görünürlüğü izleme {/*tracking-visibility-with-fragment-refs*/} - -Fragment ref'leri, görünürlük takibi ve intersection gözlemi için faydalıdır. Bu sayede, alt Component'ların ref açığa çıkarmasına gerek kalmadan içeriğin ne zaman görünür hale geldiğini izleyebilirsin: -======= -### Managing focus across a group of elements {/*managing-focus-across-elements*/} +### Bir grup element üzerinde focus yönetme {/*managing-focus-across-elements*/} -Fragment `ref`s provide `focus`, `focusLast`, and `blur` methods that operate across all DOM nodes within the Fragment: ->>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61 +Fragment `ref`leri, Fragment içindeki tüm DOM node’ları üzerinde çalışan `focus`, `focusLast` ve `blur` method’larını sağlar: diff --git a/src/content/reference/react/use.md b/src/content/reference/react/use.md index 11dab8fad..1e689ab65 100644 --- a/src/content/reference/react/use.md +++ b/src/content/reference/react/use.md @@ -4,11 +4,7 @@ title: use -<<<<<<< HEAD -`use`, [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) veya [context](/learn/passing-data-deeply-with-context) gibi bir kaynağın değerini okumanıza olanak sağlayan bir React API'ıdır. -======= -`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). ->>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61 +`use`, bir [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) veya [context](/learn/passing-data-deeply-with-context) değerini okumanızı sağlayan bir React API’sidir. ```js const value = use(resource); @@ -24,11 +20,7 @@ const value = use(resource); ### `use(context)` {/*use-context*/} -<<<<<<< HEAD -[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) veya [context](/learn/passing-data-deeply-with-context) gibi kaynakların değerini okumak için bileşeninizde `use` API'ını çağırabilirsiniz. -======= -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`. ->>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61 +Değerini okumak için `use`’u bir [context](/learn/passing-data-deeply-with-context) ile çağırın. [`useContext`](/reference/react/useContext)’in aksine, `use` loop’lar ve `if` gibi conditional statement’lar içinde çağrılabilir. ```js import { use } from 'react'; @@ -39,50 +31,26 @@ function Button() { ``` Diğer React Hook'ların aksine, Döngülerin ve `if` gibi koşullu ifadeler içerisinde `use` kullanılabilir. Diğer React Hook'lar gibi, `use` kullanan fonksiyon bir Bileşen veya Hook olmalıdır. -<<<<<<< HEAD -Bir Pomise ile çağırıldığında; `use` API, [`Suspense`](/reference/react/Suspense) ve [hata sınırları](/reference/react/Component#catching-rendering-errors-with-an-error-boundary) ile entegre olur. `use`'a iletilen Promise beklenirken, `use` çağrısı yapan bileşen askıya alınır. Eğer `use` çağrısı yapan bileşen Suspense içerisine alınırsa yedek görünüm görüntülenecektir. Promise çözümlendiğinde ise; Suspense yedek görünümü, `use` API'ı tarafından döndürülen değerleri kullanarak oluşturulan bileşenler ile yer değiştirir. Eğer `use`'a iletilen Promise reddedilir ise, en yakındaki Hata Sınırının yedek görünümü görüntülenecektir. +[Daha fazla örneği aşağıda görün.](#usage-context) -Bir Promise ile çağrıldığında, `use` API’si [`Suspense`](/reference/react/Suspense) ve [Error Boundaries](/reference/react/Component#catching-rendering-errors-with-an-error-boundary) ile entegre çalışır. `use` çağrısı yapan bileşen, `use` fonksiyonuna iletilen Promise beklemede (**pending**) olduğu sürece *askıya alınır* (**suspend olur**). Eğer bu bileşen bir Suspense boundary içine sarılmışsa, fallback içerik gösterilir. Promise çözümlendiğinde (**resolved**), Suspense fallback kaldırılır ve `use` API’si tarafından döndürülen veriyi kullanan bileşenler render edilir. Eğer `use` fonksiyonuna iletilen Promise reddedilirse (**rejected**), en yakın Error Boundary’nin fallback içeriği gösterilir. +#### Parametreler {/*context-parameters*/} -#### Parametreler {/*parameters*/} +* `context`: [`createContext`](/reference/react/createContext) ile oluşturulmuş bir [context](/learn/passing-data-deeply-with-context). -* `resource`: Bu, bir değeri okumak istediğiniz verinin kaynağıdır. Kaynak, [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) ya da [context](/learn/passing-data-deeply-with-context) olabilir. +#### Döndürür {/*context-returns*/} -#### Dönüş Değerleri {/*returns*/} +Geçirilen context için context value’yu döndürür; bu değer, çağrıyı yapan component’in üstündeki en yakın context provider tarafından belirlenir. Eğer provider yoksa, döndürülen değer [`createContext`](/reference/react/createContext)’e geçirilen `defaultValue` olur. -`use` API, [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) ya da [context](/learn/passing-data-deeply-with-context) gibi bir kaynaktan çözümlenen veriyi döndürür. +#### Uyarılar {/*context-caveats*/} -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). - -#### Caveats {/*caveats*/} - -* `use` API'si bir Bileşen veya Hook içinde çağrılmalıdır. -* [Sunucu Bileşenleri](/reference/rsc/server-components) içinde veri çekerken, `use` yerine `async` ve `await` kullanmayı tercih edin. `async` ve `await`, `await` çağrıldığında render'a başlar, oysa `use` veri çözümlandıktan sonra bileşeni yeniden render eder. -* [Sunucu Bileşenleri](/reference/rsc/server-components) içinde Promise'ler oluşturmayı ve bunları [İstemci Bileşenleri](/reference/rsc/use-client) içine iletmeyi, İstemci Bileşenleri içinde Promise'ler oluşturmaya tercih edin. Client Bileşenleri içinde oluşturulan Promise'ler her render işleminde yeniden oluşturulur. Sunucu Bileşenlerin'den İstemci Bileşenleri'e geçirilen Promise'ler yeniden render'lar arasında sabittir. [Bu örneğe bakın](#streaming-data-from-server-to-client). ---- - -## Kullanım {/*usage*/} -======= -[See more examples below.](#usage-context) - -#### Parameters {/*context-parameters*/} - -* `context`: A [context](/learn/passing-data-deeply-with-context) created with [`createContext`](/reference/react/createContext). - -#### Returns {/*context-returns*/} - -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). - -#### Caveats {/*context-caveats*/} - -* `use` must be called inside a Component or a Hook. -* Reading context with `use` is not supported in [Server Components](/reference/rsc/server-components). +* `use`, bir Component veya Hook içinde çağrılmalıdır. +* `use` ile context okumak [Server Components](/reference/rsc/server-components) içinde desteklenmez. --- ### `use(promise)` {/*use-promise*/} -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`. +Resolved value’sunu okumak için `use`’u bir [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) ile çağırın. `use` çağıran component, Promise pending durumdayken *suspend* olur. İsminin aksine, `use` bir Hook değildir. Hook’ların aksine, loop’lar ve `if` gibi conditional statement’lar içinde çağrılabilir. ```js import { use } from 'react'; @@ -114,16 +82,12 @@ The resolved value of the Promise. --- ## Usage (Context) {/*usage-context*/} ->>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61 ### `use` ile context okumak {/*reading-context-with-use*/} `use`'a [context](/learn/passing-data-deeply-with-context) aktarıldığında, [`useContext`](/reference/react/useContext) gibi çalışacaktır. `useContext` bileşende üst seviye olarak çağırılmak zorundayken; `use` ifadesi, `if` gibi koşullu ifadelerin ve `for` gibi döngü ifadelerinin içerisinde kullanılabilir. Çok daha esnek kullanılabildiğinden dolayı `use` ifadesi, `useContext` yerine tercih edilebilir. -<<<<<<< HEAD -======= -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`. ->>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61 +Bir [context](/learn/passing-data-deeply-with-context), `use`’a geçirildiğinde [`useContext`](/reference/react/useContext) ile benzer şekilde çalışır. `useContext` component’inizin top-level’ında çağrılmak zorundayken, `use` `if` gibi conditional’lar ve `for` gibi loop’lar içinde çağrılabilir. ```js [[2, 4, "theme"], [1, 4, "ThemeContext"]] import { use } from 'react'; @@ -258,15 +222,9 @@ function Button({ show, children }) { -<<<<<<< HEAD -### Sunucudan istemciye veri aktarımı {/*streaming-data-from-server-to-client*/} - -Sunucudan gelen veri; Sunucu Bileşeni'nden İstemci Bileşeni'ne Promise biçiminde prop olarak aktarılır. -======= -### Reading a Promise from context {/*reading-a-promise-from-context*/} +### Context’ten Promise okuma {/*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)`: ->>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61 +Prop drilling olmadan asynchronous data paylaşmak için, bir Promise’i context value olarak ayarlayın, ardından `use(context)` ile okuyun ve `use(promise)` ile resolve edin: ```js import { use } from 'react'; @@ -1072,11 +1030,7 @@ export default function App() { } ``` -<<<<<<< HEAD -İstemci Bileşeni prop olarak iletilen Promise'i alır ve `use` API'ına ileterek kullanır. Bu yöntem Sunucu Bileşeni içerisinde oluşturulan Promise'ten alınan verinin İstemci Bileşeni tarafından okunmasına olanak tanır. -======= -The Client Component then takes the Promise it received as a prop and passes it to the `use` API. This allows the Client Component to read the value from the Promise that was initially created by the Server Component. ->>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61 +Client Component daha sonra prop olarak aldığı Promise’i alır ve `use` API’sine geçirir. Bu, Client Component’in başlangıçta Server Component tarafından oluşturulan Promise’ten gelen değeri okumasını sağlar. ```js // message.js @@ -1089,12 +1043,7 @@ export function Message({ messagePromise }) { return

Aktarılan Mesaj: {messageContent}

; } ``` -<<<<<<< HEAD - -`Message` bir [`Suspense`](/reference/react/Suspense) içerisinde olduğu için Promise çözümleninceye kadar yedek görünüm görüntülenecektir. Promise çözümlendiğinde değer `use` API tarafından okunacak ve `Message` bileşeni Suspense'in yedek görünüm ile yer değiştirecektir. -======= -Because `Message` is wrapped in a [Suspense](/reference/react/Suspense) boundary, the fallback will be displayed until the Promise is resolved. When the Promise is resolved, the value will be read by the `use` API and the `Message` component will replace the Suspense fallback. ->>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61 +`Message`, bir [Suspense](/reference/react/Suspense) boundary’si ile sarıldığı için, Promise resolve edilene kadar fallback gösterilir. Promise resolve edildiğinde, değer `use` API’si tarafından okunur ve `Message` component’i Suspense fallback’inin yerini alır. @@ -1161,65 +1110,29 @@ root.render( -<<<<<<< HEAD - - -Sunucu Bileşeni'nden İstemci Bileşeni'ne Promise aktarıldığında çözümlenen değer sunucu ile istemci arasından geçmesi için serileştirilebilir olması gerekir. Fonksiyonlar gibi veri türleri serileştirilemezler ve Promise'in çözümlenen değeri olamazlar. - - - - -======= ->>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61 #### Promise'i Sunucu Bileşeninde mi yoksa İstemci Bileşeninde mi çözümlemeliyim? {/*resolve-promise-in-server-or-client-component*/} -<<<<<<< HEAD -Promise, Sunucu Bileşeni'nden İstemci Bileşeni'ne aktarılabilir ve İstemci Bileşeni içerisinde `use` API kullanarak çözümlenebilir. Yanı sıra istersen Promise'i Sunucu Bileşeni içerisinde `await` kullanarak çözümleyebilir ve gerekli veriyi İstemci Bileşeni içerisine prop olarak iletebilirsin. -======= -A Promise can be resolved with `await` in a Server Component, or passed as a prop to a Client Component and resolved there with `use`. +Bir Promise, bir Server Component içinde `await` ile resolve edilebilir veya bir Client Component’e prop olarak geçirilip orada `use` ile resolve edilebilir. -Using `await` in a Server Component suspends the Server Component itself, and the Client Component receives the resolved value as a prop: ->>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61 +Bir Server Component içinde `await` kullanmak Server Component’in kendisini suspend eder ve Client Component resolved value’yu prop olarak alır: ```js // Server Component export default async function App() { - // Will suspend the Server Component. + // Server Component’i suspend eder. const messageContent = await fetchMessage(); return ; } ``` -<<<<<<< HEAD -Ancak bir [Sunucu Bileşeninde](/reference/rsc/server-components) `await` kullanmak, `await` deyimi bitene kadar bileşenin oluşturulmasını engelleyecektir. Bir Sunucu Bileşeninden bir İstemci Bileşenine bir Promise geçirmek, Promise'in Sunucu Bileşeninin oluşturulmasını engellemesini önler. - - - -### Reddedilen Promise'ler ile başa çıkmak {/*dealing-with-rejected-promises*/} - -Bazen `use`'a aktarılan Promise reddedilebilir. Reddedilen Promise'leri şu şekilde yönetebilirsiniz: - -1. [Error Boundary ile kullanıcılara hata gösterme](#displaying-an-error-to-users-with-error-boundary) -2. [`Promise.catch` ile alternatif değer sağlama](#providing-an-alternative-value-with-promise-catch) - - -`use`, try-catch bloğu içerisinde çağırılamaz. Try-catch bloğu yerine [bileşeni Error Boundary içerisine ekleyin](#displaying-an-error-to-users-with-error-boundary), ya da [Promise'in `.catch` methodundan yararlanarak alternatif bir değer sağlayın](#providing-an-alternative-value-with-promise-catch). - - -#### Error Boundary ile kullanıcılara hata gösterme {/*displaying-an-error-to-users-with-error-boundary*/} - -Bir Promise reddedildiğinde kullanıcıya hata göstermek istiyorsanız, [Error Boundary](/reference/react/Component#catching-rendering-errors-with-an-error-boundary) kullanabilirsiniz. -Error Boundary kullanmak için, `use` API’sini çağırdığınız bileşeni bir Error Boundary ile sarın. -Eğer `use` fonksiyonuna iletilen Promise reddedilirse, Error Boundary için tanımlanan fallback içerik görüntülenecektir. -======= -A Server Component can also start a Promise without awaiting it and pass the Promise to a Client Component. The Server Component returns immediately, and the Client Component suspends when it calls `use`: +Bir Server Component ayrıca bir Promise’i await etmeden başlatabilir ve Promise’i bir Client Component’e geçirebilir. Server Component hemen return eder ve Client Component `use` çağırdığında suspend olur: ```js // Server Component export default function App() { - // Not awaited: starts here, resolves on the client. + // Await edilmedi: burada başlar, client’ta resolve olur. const messagePromise = fetchMessage(); return ; } @@ -1231,28 +1144,27 @@ export default function App() { import { use } from 'react'; export function Message({ messagePromise }) { - // Will suspend until the data is available. + // Data available olana kadar suspend eder. const messageContent = use(messagePromise); return

{messageContent}

; } ``` -Prefer `await` in a Server Component when possible, since it keeps the data fetching on the server. If a Server Component above already awaits the data, pass the resolved value down as a prop instead of creating a new Promise to call `use`. +Mümkün olduğunda Server Component içinde `await` kullanmayı tercih edin; çünkü bu, data fetching’i server tarafında tutar. Eğer üstteki bir Server Component data’yı zaten await ediyorsa, `use` çağırmak için yeni bir Promise oluşturmak yerine resolved value’yu prop olarak aşağı geçirin. -You can also pass promise as a prop to a Client Component without awaiting it, and then read it with `use(promise)` to suspend deeper in the tree. This allows more of the surrounding UI to complete while the Promise is pending. A common case is interactive content like popovers and tooltips, where the data is needed only after a hover or click. Client Components can't `await`, so they rely on `use` to suspend on a Promise. +Ayrıca promise’i await etmeden bir Client Component’e prop olarak geçirebilir ve ardından tree’nin daha derininde suspend etmek için `use(promise)` ile okuyabilirsiniz. Bu, Promise pending durumdayken çevredeki UI’ın daha büyük bir kısmının tamamlanmasına olanak tanır. Yaygın bir durum, popover ve tooltip gibi interactive content’lerdir; burada data yalnızca hover veya click sonrasında gerekir. Client Component’ler `await` kullanamaz, bu yüzden bir Promise üzerinde suspend olmak için `use`’a güvenirler. -In either case, wrap the component that reads the Promise in a Suspense boundary so React can show a fallback while the Promise is pending. See [Revealing content together at once](/reference/react/Suspense#revealing-content-together-at-once) for guidance on boundary placement. +Her iki durumda da, Promise’i okuyan component’i bir Suspense boundary ile sarın; böylece React, Promise pending durumdayken bir fallback gösterebilir. Boundary placement konusunda rehberlik için [Revealing content together at once](/reference/react/Suspense#revealing-content-together-at-once) bölümüne bakın. --- -### Displaying an error with an Error Boundary {/*displaying-an-error-with-an-error-boundary*/} +### Error Boundary ile hata gösterme {/*displaying-an-error-with-an-error-boundary*/} -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. +`use`’a geçirilen Promise rejected olursa, error en yakın [Error Boundary](/reference/react/Component#catching-rendering-errors-with-an-error-boundary)’ye propagate edilir. Promise rejected olduğunda bir fallback göstermek için `use` çağıran component’i bir Error Boundary ile sarın. -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. ->>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61 +Aşağıdaki örnekte, `fetchData` ilk denemede reject olur ve retry sırasında başarılı olur. Error Boundary rejection’ı yakalar ve "Try again" button’u olan bir fallback gösterir. @@ -1273,33 +1185,22 @@ export default function App() { } return ( -<<<<<<< HEAD - ⚠️Bir şeyler yanlış gitti

}> - ⌛Mesaj indiriliyor...

}> - -======= ( <> -

⚠️ Something went wrong loading the albums.

- +

⚠️ Albümler yüklenirken bir sorun oluştu.

+ )} > - Loading...

}> + Yükleniyor...

}> ->>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61
); } -<<<<<<< HEAD -function Message({ messagePromise }) { - const content = use(messagePromise); - return

Aktarılan mesaj: {content}

; -======= function Albums({ albumsPromise }) { const albums = use(albumsPromise); return ( @@ -1311,14 +1212,13 @@ function Albums({ albumsPromise }) { ))} ); ->>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61 } ``` ```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. +// Not: data fetching’i nasıl yapacağınız, +// Suspense ile birlikte kullandığınız framework’e bağlıdır. +// Normalde caching logic bir framework içinde olur. let cache = new Map(); let retried = false; @@ -1330,46 +1230,12 @@ export function fetchData(url) { return cache.get(url); } -<<<<<<< HEAD -export default function App() { - const [messagePromise, setMessagePromise] = useState(null); - const [show, setShow] = useState(false); - function download() { - setMessagePromise(fetchMessage()); - setShow(true); - } - - if (show) { - return ; - } else { - return ; - } -======= export function refetchData(url) { cache.delete(url); retried = true; return fetchData(url); ->>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61 } -<<<<<<< HEAD -```js src/index.js hidden -import React, { StrictMode } from 'react'; -import { createRoot } from 'react-dom/client'; -import './styles.css'; - -// TODO: Bu örneği, -// Codesandbox Sunucu Bileşeni -// demo ortamı oluşturulduğunda güncelleyin -import App from './App'; - -const root = createRoot(document.getElementById('root')); -root.render( - - - -); -======= async function getData(url) { // Add a fake delay to make the loading state visible. await new Promise(resolve => setTimeout(resolve, 1000)); @@ -1399,7 +1265,6 @@ async function getData(url) { } throw new Error('Not implemented'); } ->>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61 ``` ```json package.json hidden @@ -1415,66 +1280,13 @@ async function getData(url) { ```
-<<<<<<< HEAD -#### `Promise.catch` methodunu kullanarak alternatif bir veri sunmak {/*providing-an-alternative-value-with-promise-catch*/} - -Eğer `use`'a aktarılan Promise reddedildiğinde yerine alternatif bir değer sağlamak istiyorsan Promise'in [`catch`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch) methodunu kullanabilirsin. - -```js [[1, 6, "catch"],[2, 7, "return"]] -import { Message } from './message.js'; - -export default function App() { - const messagePromise = new Promise((resolve, reject) => { - reject(); - }).catch(() => { - return "yeni mesaj bulunamadı."; - }); - - return ( - Mesaj bekleniyor...

}> - -
- ); -} -``` - -Promise'in `catch` methodunu kullanmak için Promise objesinden `catch`'i çağır. `catch` tek bir argüman alır: Bir hata mesajını argüman olarak alan bir fonksiyon. `catch`'e geçirilen fonskiyon tarafından döndürülen her şey, Promise'in çözümlenen değeri olarak kullanılacaktır. - -======= ->>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61 --- ## Sorun Giderme {/*troubleshooting*/} -<<<<<<< HEAD -### "Suspense İstisnası: Bu gerçek bir hata değil!" {/*suspense-exception-error*/} - -Ya `use` fonksiyonunu bir **React Component** veya **Hook** fonksiyonu dışında çağırıyorsunuz, -ya da `use`’u bir **try–catch** bloğu içinde çağırıyorsunuz. Eğer `use`’u bir try–catch bloğu içinde çağırıyorsanız, bileşeninizi bir **Error Boundary** ile sarın, -veya Promise’in `catch` metodunu kullanarak hatayı yakalayın ve Promise’i başka bir değerle çözümleyin (**resolve edin**). [Bu örneklere bakın](#dealing-with-rejected-promises). - -Eğer `use`'u bir React Bileşeni veya Hook fonksiyonu dışında çağırıyorsanız `use` çağrısını bir React Bileşeni veya Hook fonksiyonu içerisine taşıyın. - -```jsx -function MessageComponent({messagePromise}) { - function download() { - // ❌ `use`, bir Bileşen veya Hook olmayan fonksiyon tarafından çağırılıyor - const message = use(messagePromise); - // ... -``` - -Bunun yerine, `use` fonksiyonunu herhangi bir bileşen kapanışının dışında çağırın. `use` fonksiyonunu çağıran fonksiyon bir bileşen veya Hook olmalıdır. - -```jsx -function MessageComponent({messagePromise}) { - // ✅ `use`, bir component’ten çağrılıyor. - const message = use(messagePromise); - // ... -``` -======= -### I'm getting an error: "Suspense Exception: This is not a real error!" {/*suspense-exception-error*/} +### Şu hatayı alıyorum: "Suspense Exception: This is not a real error!" {/*suspense-exception-error*/} -You are calling `use` inside a try-catch block. `use` throws internally to integrate with Suspense, so it cannot be wrapped in try-catch. Instead, wrap the component that calls `use` in an [Error Boundary](#displaying-an-error-with-an-error-boundary) to handle errors. +`use`’u bir try-catch block’u içinde çağırıyorsunuz. `use`, Suspense ile entegre olmak için internal olarak throw eder, bu yüzden try-catch ile sarılamaz. Bunun yerine, error’ları handle etmek için `use` çağıran component’i bir [Error Boundary](#displaying-an-error-with-an-error-boundary) ile sarın. ```jsx function Albums({ albumsPromise }) { @@ -1487,7 +1299,7 @@ function Albums({ albumsPromise }) { // ... ``` -Instead, wrap the component in an Error Boundary: +Bunun yerine, component’i bir Error Boundary ile sarın: ```jsx function Albums({ albumsPromise }) { @@ -1505,11 +1317,11 @@ function Albums({ albumsPromise }) { --- -### I'm getting a warning: "A component was suspended by an uncached promise" {/*uncached-promise-error*/} +### Şu uyarıyı alıyorum: "A component was suspended by an uncached promise" {/*uncached-promise-error*/} -The Promise passed to `use` is not cached, so React cannot reuse it across re-renders. +`use`’a geçirilen Promise cache’lenmemiştir, bu yüzden React onu re-render’lar arasında yeniden kullanamaz. -This commonly happens when calling `fetch` or an `async` function directly in render: +Bu durum genellikle render sırasında doğrudan `fetch` veya bir `async` function çağrıldığında olur: ```js function Albums() { @@ -1519,12 +1331,11 @@ function Albums() { } ``` -To fix this, cache the Promise so the same instance is reused: +Bunu düzeltmek için, aynı instance’ın yeniden kullanılmasını sağlayacak şekilde Promise’i cache’leyin: ```js // ✅ fetchData returns the same Promise for the same URL const albums = use(fetchData('/albums')); ``` -See [caching Promises for Client Components](#caching-promises-for-client-components) for more details. ->>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61 +Daha fazla detay için [Client Components için Promise cache’leme](#caching-promises-for-client-components) bölümüne bakın. diff --git a/src/content/reference/react/useLayoutEffect.md b/src/content/reference/react/useLayoutEffect.md index a69239165..56c789ad9 100644 --- a/src/content/reference/react/useLayoutEffect.md +++ b/src/content/reference/react/useLayoutEffect.md @@ -47,11 +47,7 @@ function Tooltip() { #### Parametreler {/*parameters*/} -<<<<<<< HEAD -* `setup`: Effect’inizin mantığını içeren fonksiyondur. `setup` fonksiyonunuz isteğe bağlı olarak bir *cleanup* (temizleme) fonksiyonu döndürebilir. Bileşeniniz [commit edilmeden önce](/learn/render-and-commit#step-3-react-commits-changes-to-the-dom), React `setup` fonksiyonunu çalıştırır. Dependency’leri değişmiş her commit’ten sonra React, önce (varsa) eski değerlerle *cleanup* fonksiyonunu çalıştırır, ardından yeni değerlerle `setup` fonksiyonunu çalıştırır. Bileşeniniz DOM’dan kaldırılmadan önce React *cleanup* fonksiyonunu çalıştırır. -======= -* `setup`: The function with your Effect's logic. Your setup function may also optionally return a *cleanup* function. After your [component commits](/learn/render-and-commit#step-3-react-commits-changes-to-the-dom) to the DOM and before the browser repaints the screen, React will run your setup function. After every commit with changed dependencies, React will first run the cleanup function (if you provided it) with the old values, and then run your setup function with the new values. Before your component is removed from the DOM, React will run your cleanup function. ->>>>>>> 152a471aa9ac2f6f0f3e64c04f39da790d40cf61 +* `setup`: Effect mantığınızı içeren fonksiyon. setup fonksiyonunuz isteğe bağlı olarak bir *cleanup* fonksiyonu da döndürebilir. Component’iniz DOM’a [commit ettikten](/learn/render-and-commit#step-3-react-commits-changes-to-the-dom) sonra ve browser ekranı yeniden paint etmeden önce, React setup fonksiyonunuzu çalıştırır. Değişen dependency’lerle gerçekleşen her commit’ten sonra React önce eski değerlerle cleanup fonksiyonunu çalıştırır (eğer sağladıysanız), ardından yeni değerlerle setup fonksiyonunuzu çalıştırır. Component’iniz DOM’dan kaldırılmadan önce React cleanup fonksiyonunuzu çalıştırır. * **opsiyonel** `dependencies`: `setup` kodu içinde referans verilen tüm reactive value’ların listesidir. Reactive value’lar; props, state ve bileşen gövdesi içinde doğrudan tanımlanan tüm değişkenler ve fonksiyonları kapsar. Eğer linter’ınız [React için yapılandırılmışsa](/learn/editor-setup#linting), her reactive value’nun dependency olarak doğru şekilde belirtildiğini doğrular. Dependency listesi sabit sayıda öğe içermeli ve `[dep1, dep2, dep3]` şeklinde inline olarak yazılmalıdır. React, her bir dependency’yi önceki değeriyle [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) karşılaştırması kullanarak kıyaslar. Bu argümanı atladığınızda, Effect’iniz bileşenin her commit’inden sonra yeniden çalışır.