From 02ecdeda7caf45ac950c01b6cc9be275571f8130 Mon Sep 17 00:00:00 2001 From: Dominik Dorfmeister Date: Mon, 13 Oct 2025 11:13:24 +0200 Subject: [PATCH 01/64] Update caveats for Activity rendering behavior (#8067) Co-authored-by: Sebastian "Sebbie" Silbermann --- src/content/reference/react/Activity.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/content/reference/react/Activity.md b/src/content/reference/react/Activity.md index cf73efb26..53c38f64f 100644 --- a/src/content/reference/react/Activity.md +++ b/src/content/reference/react/Activity.md @@ -48,6 +48,7 @@ In this way, Activity can be thought of as a mechanism for rendering "background #### Caveats {/*caveats*/} - If an Activity is rendered inside of a [ViewTransition](/reference/react/ViewTransition), and it becomes visible as a result of an update caused by [startTransition](/reference/react/startTransition), it will activate the ViewTransition's `enter` animation. If it becomes hidden, it will activate its `exit` animation. +- An Activity that just renders text will not render anything rather than rendering hidden text, because there’s no corresponding DOM element to apply visibility changes to. For example, `` will not produce any output in the DOM for `const ComponentThatJustReturnsText = () => "Hello, World!"`. --- @@ -1248,4 +1249,4 @@ When an `` is "hidden", all its children's Effects are cleaned up. Con If you're relying on an Effect mounting to clean up a component's side effects, refactor the Effect to do the work in the returned cleanup function instead. -To eagerly find problematic Effects, we recommend adding [``](/reference/react/StrictMode) which will eagerly perform Activity unmounts and mounts to catch any unexpected side-effects. \ No newline at end of file +To eagerly find problematic Effects, we recommend adding [``](/reference/react/StrictMode) which will eagerly perform Activity unmounts and mounts to catch any unexpected side-effects. From a677ba342473ada89cfd6730595ca90d6055fc41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Mon, 13 Oct 2025 12:39:04 +0200 Subject: [PATCH 02/64] Fragment refs - Remove unused ref from focus fragment example (#8056) --- src/content/reference/react/Fragment.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/content/reference/react/Fragment.md b/src/content/reference/react/Fragment.md index 3b771d408..7399ee240 100644 --- a/src/content/reference/react/Fragment.md +++ b/src/content/reference/react/Fragment.md @@ -317,8 +317,6 @@ Fragment refs provide focus management methods that work across all DOM nodes wi import { Fragment, useRef } from 'react'; function FocusFragment({ children }) { - const fragmentRef = useRef(null); - return ( fragmentInstance?.focus()}> {children} From 9ef1c4741776a14b034711cc03e4124ccc53e337 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 15 Oct 2025 13:52:59 +0530 Subject: [PATCH 03/64] fix: Breaking up a sentence to make it easier to understand (#8078) --- src/content/learn/understanding-your-ui-as-a-tree.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/understanding-your-ui-as-a-tree.md b/src/content/learn/understanding-your-ui-as-a-tree.md index 2abf7affc..afc38cd33 100644 --- a/src/content/learn/understanding-your-ui-as-a-tree.md +++ b/src/content/learn/understanding-your-ui-as-a-tree.md @@ -20,7 +20,7 @@ React, and many other UI libraries, model UI as a tree. Thinking of your app as ## Your UI as a tree {/*your-ui-as-a-tree*/} -Trees are a relationship model between items and UI is often represented using tree structures. For example, browsers use tree structures to model HTML ([DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model/Introduction)) and CSS ([CSSOM](https://developer.mozilla.org/docs/Web/API/CSS_Object_Model)). Mobile platforms also use trees to represent their view hierarchy. +Trees are a relationship model between items. The UI is often represented using tree structures. For example, browsers use tree structures to model HTML ([DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model/Introduction)) and CSS ([CSSOM](https://developer.mozilla.org/docs/Web/API/CSS_Object_Model)). Mobile platforms also use trees to represent their view hierarchy. From c8843f794440f76950f5ee3e0b7aaea6630eefe9 Mon Sep 17 00:00:00 2001 From: Yonas650 <111200835+Yonas650@users.noreply.github.com> Date: Thu, 16 Oct 2025 13:54:30 -0400 Subject: [PATCH 04/64] docs: capitalize Error Boundary concept across docs (#6713) (#8077) --- src/content/reference/react/Component.md | 14 +++++++------- src/content/reference/react/Suspense.md | 2 +- src/content/reference/react/use.md | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/content/reference/react/Component.md b/src/content/reference/react/Component.md index 09acbc7d6..9d2d1007b 100644 --- a/src/content/reference/react/Component.md +++ b/src/content/reference/react/Component.md @@ -206,7 +206,7 @@ There is no exact equivalent for `constructor` in function components. To declar If you define `componentDidCatch`, React will call it when some child component (including distant children) throws an error during rendering. This lets you log that error to an error reporting service in production. -Typically, it is used together with [`static getDerivedStateFromError`](#static-getderivedstatefromerror) which lets you update state in response to an error and display an error message to the user. A component with these methods is called an *error boundary.* +Typically, it is used together with [`static getDerivedStateFromError`](#static-getderivedstatefromerror) which lets you update state in response to an error and display an error message to the user. A component with these methods is called an *Error Boundary*. [See an example.](#catching-rendering-errors-with-an-error-boundary) @@ -932,7 +932,7 @@ Defining `defaultProps` in class components is similar to using [default values] If you define `static getDerivedStateFromError`, React will call it when a child component (including distant children) throws an error during rendering. This lets you display an error message instead of clearing the UI. -Typically, it is used together with [`componentDidCatch`](#componentdidcatch) which lets you send the error report to some analytics service. A component with these methods is called an *error boundary.* +Typically, it is used together with [`componentDidCatch`](#componentdidcatch) which lets you send the error report to some analytics service. A component with these methods is called an *Error Boundary*. [See an example.](#catching-rendering-errors-with-an-error-boundary) @@ -1267,11 +1267,11 @@ We recommend defining components as functions instead of classes. [See how to mi --- -### Catching rendering errors with an error boundary {/*catching-rendering-errors-with-an-error-boundary*/} +### Catching rendering errors with an Error Boundary {/*catching-rendering-errors-with-an-error-boundary*/} -By default, if your application throws an error during rendering, React will remove its UI from the screen. To prevent this, you can wrap a part of your UI into an *error boundary*. An error boundary is a special component that lets you display some fallback UI instead of the part that crashed--for example, an error message. +By default, if your application throws an error during rendering, React will remove its UI from the screen. To prevent this, you can wrap a part of your UI into an *Error Boundary*. An Error Boundary is a special component that lets you display some fallback UI instead of the part that crashed--for example, an error message. -To implement an error boundary component, you need to provide [`static getDerivedStateFromError`](#static-getderivedstatefromerror) which lets you update state in response to an error and display an error message to the user. You can also optionally implement [`componentDidCatch`](#componentdidcatch) to add some extra logic, for example, to log the error to an analytics service. +To implement an Error Boundary component, you need to provide [`static getDerivedStateFromError`](#static-getderivedstatefromerror) which lets you update state in response to an error and display an error message to the user. You can also optionally implement [`componentDidCatch`](#componentdidcatch) to add some extra logic, for example, to log the error to an analytics service. With [`captureOwnerStack`](/reference/react/captureOwnerStack) you can include the Owner Stack during development. @@ -1324,11 +1324,11 @@ Then you can wrap a part of your component tree with it: If `Profile` or its child component throws an error, `ErrorBoundary` will "catch" that error, display a fallback UI with the error message you've provided, and send a production error report to your error reporting service. -You don't need to wrap every component into a separate error boundary. When you think about the [granularity of error boundaries,](https://www.brandondail.com/posts/fault-tolerance-react) consider where it makes sense to display an error message. For example, in a messaging app, it makes sense to place an error boundary around the list of conversations. It also makes sense to place one around every individual message. However, it wouldn't make sense to place a boundary around every avatar. +You don't need to wrap every component into a separate Error Boundary. When you think about the [granularity of Error Boundaries,](https://www.brandondail.com/posts/fault-tolerance-react) consider where it makes sense to display an error message. For example, in a messaging app, it makes sense to place an Error Boundary around the list of conversations. It also makes sense to place one around every individual message. However, it wouldn't make sense to place a boundary around every avatar. -There is currently no way to write an error boundary as a function component. However, you don't have to write the error boundary class yourself. For example, you can use [`react-error-boundary`](https://github.com/bvaughn/react-error-boundary) instead. +There is currently no way to write an Error Boundary as a function component. However, you don't have to write the Error Boundary class yourself. For example, you can use [`react-error-boundary`](https://github.com/bvaughn/react-error-boundary) instead. diff --git a/src/content/reference/react/Suspense.md b/src/content/reference/react/Suspense.md index 4fce69d69..fa5b4439f 100644 --- a/src/content/reference/react/Suspense.md +++ b/src/content/reference/react/Suspense.md @@ -2008,7 +2008,7 @@ However, now imagine you're navigating between two different user profiles. In t If you use one of the [streaming server rendering APIs](/reference/react-dom/server) (or a framework that relies on them), React will also use your `` boundaries to handle errors on the server. If a component throws an error on the server, React will not abort the server render. Instead, it will find the closest `` component above it and include its fallback (such as a spinner) into the generated server HTML. The user will see a spinner at first. -On the client, React will attempt to render the same component again. If it errors on the client too, React will throw the error and display the closest [error boundary.](/reference/react/Component#static-getderivedstatefromerror) However, if it does not error on the client, React will not display the error to the user since the content was eventually displayed successfully. +On the client, React will attempt to render the same component again. If it errors on the client too, React will throw the error and display the closest [Error Boundary.](/reference/react/Component#static-getderivedstatefromerror) However, if it does not error on the client, React will not display the error to the user since the content was eventually displayed successfully. You can use this to opt out some components from rendering on the server. To do this, throw an error in the server environment and then wrap them in a `` boundary to replace their HTML with fallbacks: diff --git a/src/content/reference/react/use.md b/src/content/reference/react/use.md index 5daae72f0..dc43fa228 100644 --- a/src/content/reference/react/use.md +++ b/src/content/reference/react/use.md @@ -33,7 +33,7 @@ function MessageComponent({ messagePromise }) { 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. -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. +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. [See more examples below.](#usage) @@ -320,16 +320,16 @@ But using `await` in a [Server Component](/reference/rsc/server-components) will In some cases a Promise passed to `use` could be rejected. You can handle rejected Promises by either: -1. [Displaying an error to users with an error boundary.](#displaying-an-error-to-users-with-error-boundary) +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) `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). -#### Displaying an error to users with an error boundary {/*displaying-an-error-to-users-with-error-boundary*/} +#### Displaying an error to users with an Error Boundary {/*displaying-an-error-to-users-with-error-boundary*/} -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. +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. @@ -440,7 +440,7 @@ To use the Promise's `catch` method, call Date: Fri, 17 Oct 2025 00:58:22 +0700 Subject: [PATCH 05/64] docs: update recommended full-stack React framework from Remix to React Router (#8076) --- src/components/Layout/HomeContent.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Layout/HomeContent.js b/src/components/Layout/HomeContent.js index 3cf7d5c2c..9cc26bdaa 100644 --- a/src/components/Layout/HomeContent.js +++ b/src/components/Layout/HomeContent.js @@ -253,7 +253,7 @@ export function HomeContent() { doesn’t prescribe how to do routing and data fetching. To build an entire app with React, we recommend a full-stack React framework like Next.js or{' '} - Remix. + React Router. From 55e37af6c5967581c351834a069bb64821407ec1 Mon Sep 17 00:00:00 2001 From: Aris Markogiannakis Date: Thu, 16 Oct 2025 11:59:28 -0700 Subject: [PATCH 06/64] Update conference listings for 2025 and 2026 (#8069) Removed CityJS New Delhi 2025 conference details and added CityJS Singapore 2026, CityJS New Delhi 2026, and CityJS London 2026 conference details. --- src/content/community/conferences.md | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/content/community/conferences.md b/src/content/community/conferences.md index 9354dc9c3..9cd83cffc 100644 --- a/src/content/community/conferences.md +++ b/src/content/community/conferences.md @@ -35,12 +35,6 @@ October 31 - November 01, 2025. In-person in Goa, India (hybrid event) + Oct 15 [Website](https://www.reactindia.io) - [Twitter](https://twitter.com/react_india) - [Facebook](https://www.facebook.com/ReactJSIndia) - [Youtube](https://www.youtube.com/channel/UCaFbHCBkPvVv1bWs_jwYt3w) - -### CityJS New Delhi 2025 {/*cityjs-newdelhi*/} -November 6-7, 2025. In-person in New Delhi, India - -[Website](https://india.cityjsconf.org/) - [Twitter](https://x.com/cityjsconf) - [Bluesky](https://bsky.app/profile/cityjsconf.bsky.social) - ### React Summit US 2025 {/*react-summit-us-2025*/} November 18 - 21, 2025. In-person in New York, USA + remote (hybrid event) @@ -51,12 +45,29 @@ November 28 & December 1, 2025. In-person in London, UK + online (hybrid event) [Website](https://reactadvanced.com/) - [Twitter](https://x.com/reactadvanced) +### CityJS Singapore 2026 {/*cityjs-singapore-2026*/} +February 4-6, 2026. In-person in Singapore + +[Website](https://india.cityjsconf.org/) - [Twitter](https://x.com/cityjsconf) - [Bluesky](https://bsky.app/profile/cityjsconf.bsky.social) + +### CityJS New Delhi 2026 {/*cityjs-newdelhi-2026*/} +February 12-13, 2026. In-person in New Delhi, India + +[Website](https://india.cityjsconf.org/) - [Twitter](https://x.com/cityjsconf) - [Bluesky](https://bsky.app/profile/cityjsconf.bsky.social) + + ### React Paris 2026 {/*react-paris-2026*/} March 26 - 27, 2026. In-person in Paris, France (hybrid event) [Website](https://react.paris/) - [Twitter](https://x.com/BeJS_) +### CityJS London 2026 {/*cityjs-london-2026*/} +April 14-17, 2026. In-person in London + +[Website](https://india.cityjsconf.org/) - [Twitter](https://x.com/cityjsconf) - [Bluesky](https://bsky.app/profile/cityjsconf.bsky.social) + + ## Past Conferences {/*past-conferences*/} From 44e94f3e756fbc0ebefb1ab1912ac5e33e564577 Mon Sep 17 00:00:00 2001 From: Antonin Gauthier <45275394+gramsco@users.noreply.github.com> Date: Thu, 16 Oct 2025 21:07:48 +0200 Subject: [PATCH 07/64] Fix typo in useRef.md (#8060) --- src/content/reference/react/useRef.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/reference/react/useRef.md b/src/content/reference/react/useRef.md index e87ef6b8a..6f7728f0a 100644 --- a/src/content/reference/react/useRef.md +++ b/src/content/reference/react/useRef.md @@ -573,7 +573,7 @@ export default function MyInput({ value, onChange }) { } ``` -And then add `ref` to the list of props your component accepts and pass `ref` as a prop to the relevent child [built-in component](/reference/react-dom/components/common) like this: +And then add `ref` to the list of props your component accepts and pass `ref` as a prop to the relevant child [built-in component](/reference/react-dom/components/common) like this: ```js {1,6} function MyInput({ value, onChange, ref }) { From 4b920015938767d6f1cd9ea24b1a37e5b6259c6e Mon Sep 17 00:00:00 2001 From: Ritik Sachan Date: Fri, 17 Oct 2025 02:05:46 +0530 Subject: [PATCH 08/64] Fix typo in Comments component (#7258) --- src/content/reference/rsc/server-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/reference/rsc/server-components.md b/src/content/reference/rsc/server-components.md index f27fa8b86..9902212b5 100644 --- a/src/content/reference/rsc/server-components.md +++ b/src/content/reference/rsc/server-components.md @@ -293,7 +293,7 @@ function Comments({commentsPromise}) { // NOTE: this will resume the promise from the server. // It will suspend until the data is available. const comments = use(commentsPromise); - return comments.map(commment =>

{comment}

); + return comments.map(comment =>

{comment}

); } ``` From 593fa1cf0a6745a2a94ae502c0fee35bb59798ef Mon Sep 17 00:00:00 2001 From: WuMingDao <146366930+WuMingDao@users.noreply.github.com> Date: Fri, 17 Oct 2025 04:38:45 +0800 Subject: [PATCH 09/64] docs: fix symbol in prerenderToNodeStream.md (#8019) --- .../reference/react-dom/static/prerenderToNodeStream.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/reference/react-dom/static/prerenderToNodeStream.md b/src/content/reference/react-dom/static/prerenderToNodeStream.md index 961587803..7a31f66a1 100644 --- a/src/content/reference/react-dom/static/prerenderToNodeStream.md +++ b/src/content/reference/react-dom/static/prerenderToNodeStream.md @@ -4,7 +4,7 @@ title: prerenderToNodeStream -`prerenderToNodeStream` renders a React tree to a static HTML string using a [Node.js Stream.](https://nodejs.org/api/stream.html). +`prerenderToNodeStream` renders a React tree to a static HTML string using a [Node.js Stream.](https://nodejs.org/api/stream.html) ```js const {prelude, postponed} = await prerenderToNodeStream(reactNode, options?) @@ -88,7 +88,7 @@ The static `prerenderToNodeStream` API is used for static server-side generation ### Rendering a React tree to a stream of static HTML {/*rendering-a-react-tree-to-a-stream-of-static-html*/} -Call `prerenderToNodeStream` to render your React tree to static HTML into a [Node.js Stream.](https://nodejs.org/api/stream.html): +Call `prerenderToNodeStream` to render your React tree to static HTML into a [Node.js Stream](https://nodejs.org/api/stream.html): ```js [[1, 5, ""], [2, 6, "['/main.js']"]] import { prerenderToNodeStream } from 'react-dom/static'; From df7592779ad19f006dfd7167c49a15b0b72f0c5c Mon Sep 17 00:00:00 2001 From: Alejo Date: Thu, 16 Oct 2025 17:49:35 -0300 Subject: [PATCH 10/64] docs: fix server components link text to match target section heading (#8026) * Fix Server Components link text to match target section heading Change "React Server Components" to "Full-stack frameworks" in the server-components.md link text to accurately reflect the destination section heading * Remove unnecessary RSC tags from Server Components documentation --- src/content/reference/rsc/server-components.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/content/reference/rsc/server-components.md b/src/content/reference/rsc/server-components.md index 9902212b5..cf33f7d24 100644 --- a/src/content/reference/rsc/server-components.md +++ b/src/content/reference/rsc/server-components.md @@ -2,12 +2,6 @@ title: Server Components --- - - -Server Components are for use in [React Server Components](/learn/start-a-new-react-project#full-stack-frameworks). - - - Server Components are a new type of Component that renders ahead of time, before bundling, in an environment separate from your client app or SSR server. From 7571898c0afd33a1c72e3447cd93e297206d27cf Mon Sep 17 00:00:00 2001 From: kenkam Date: Thu, 16 Oct 2025 21:56:31 +0100 Subject: [PATCH 11/64] Fix cat scrolling example (#7980) --- src/content/reference/react/StrictMode.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/reference/react/StrictMode.md b/src/content/reference/react/StrictMode.md index 4a7db8748..16e8d9e60 100644 --- a/src/content/reference/react/StrictMode.md +++ b/src/content/reference/react/StrictMode.md @@ -1170,7 +1170,7 @@ export default function CatFriends() { console.log('❌ Too many cats in the list!'); } return () => { - list.splice(list.indexOf(item)); + list.splice(list.indexOf(item), 1); console.log(`❌ Removing cat from the map. Total cats: ${itemsRef.current.length}`); } }} From 6cb7fea2507be3bb19e910757f848024f4576f0f Mon Sep 17 00:00:00 2001 From: WuMingDao <146366930+WuMingDao@users.noreply.github.com> Date: Fri, 17 Oct 2025 04:59:27 +0800 Subject: [PATCH 12/64] Update hooks link to /reference/react/hooks in /reference/react/apisapis.md (#7990) Because components link to /reference/react/components, I think hooks should link to /reference/react/hooks. --- src/content/reference/react/apis.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/reference/react/apis.md b/src/content/reference/react/apis.md index 6cb990908..777b8fc7b 100644 --- a/src/content/reference/react/apis.md +++ b/src/content/reference/react/apis.md @@ -4,7 +4,7 @@ title: "Built-in React APIs" -In addition to [Hooks](/reference/react) and [Components](/reference/react/components), the `react` package exports a few other APIs that are useful for defining components. This page lists all the remaining modern React APIs. +In addition to [Hooks](/reference/react/hooks) and [Components](/reference/react/components), the `react` package exports a few other APIs that are useful for defining components. This page lists all the remaining modern React APIs. From ee5b6727ebeff73be5a61b8cabd280ab73e8f7da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rado=C5=A1=20Mili=C4=87ev?= <40705899+rammba@users.noreply.github.com> Date: Thu, 16 Oct 2025 23:05:44 +0200 Subject: [PATCH 13/64] Fix ordered list numbering in useCallback.md (#8011) --- src/content/reference/react/useCallback.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/content/reference/react/useCallback.md b/src/content/reference/react/useCallback.md index ed774d92c..cb5a3454e 100644 --- a/src/content/reference/react/useCallback.md +++ b/src/content/reference/react/useCallback.md @@ -236,10 +236,10 @@ Note that `useCallback` does not prevent *creating* the function. You're always **In practice, you can make a lot of memoization unnecessary by following a few principles:** 1. When a component visually wraps other components, let it [accept JSX as children.](/learn/passing-props-to-a-component#passing-jsx-as-children) Then, if the wrapper component updates its own state, React knows that its children don't need to re-render. -1. Prefer local state and don't [lift state up](/learn/sharing-state-between-components) any further than necessary. Don't keep transient state like forms and whether an item is hovered at the top of your tree or in a global state library. -1. Keep your [rendering logic pure.](/learn/keeping-components-pure) If re-rendering a component causes a problem or produces some noticeable visual artifact, it's a bug in your component! Fix the bug instead of adding memoization. -1. Avoid [unnecessary Effects that update state.](/learn/you-might-not-need-an-effect) Most performance problems in React apps are caused by chains of updates originating from Effects that cause your components to render over and over. -1. Try to [remove unnecessary dependencies from your Effects.](/learn/removing-effect-dependencies) For example, instead of memoization, it's often simpler to move some object or a function inside an Effect or outside the component. +2. Prefer local state and don't [lift state up](/learn/sharing-state-between-components) any further than necessary. Don't keep transient state like forms and whether an item is hovered at the top of your tree or in a global state library. +3. Keep your [rendering logic pure.](/learn/keeping-components-pure) If re-rendering a component causes a problem or produces some noticeable visual artifact, it's a bug in your component! Fix the bug instead of adding memoization. +4. Avoid [unnecessary Effects that update state.](/learn/you-might-not-need-an-effect) Most performance problems in React apps are caused by chains of updates originating from Effects that cause your components to render over and over. +5. Try to [remove unnecessary dependencies from your Effects.](/learn/removing-effect-dependencies) For example, instead of memoization, it's often simpler to move some object or a function inside an Effect or outside the component. If a specific interaction still feels laggy, [use the React Developer Tools profiler](https://legacy.reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html) to see which components benefit the most from memoization, and add memoization where needed. These principles make your components easier to debug and understand, so it's good to follow them in any case. In long term, we're researching [doing memoization automatically](https://www.youtube.com/watch?v=lGEMwh32soc) to solve this once and for all. From f93cb2e062bd25c82a6e8395963ba4450fa4c435 Mon Sep 17 00:00:00 2001 From: WuMingDao <146366930+WuMingDao@users.noreply.github.com> Date: Fri, 17 Oct 2025 05:06:11 +0800 Subject: [PATCH 14/64] doc: Update from /react to /react/hooks in /reference/react-dom/hooks/index.md (#7983) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Suggestion: Link to /reference/react/hooks rather than /reference/react. The preceding sentence refers to “If you are looking for Hooks that are supported in web browsers *and other environments* see [the React Hooks page](/reference/react/hooks). This page lists all the Hooks in the `react-dom` package.” which matches the React Hooks page better. --- src/content/reference/react-dom/hooks/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/reference/react-dom/hooks/index.md b/src/content/reference/react-dom/hooks/index.md index 5dfb07d82..5bda2b5ad 100644 --- a/src/content/reference/react-dom/hooks/index.md +++ b/src/content/reference/react-dom/hooks/index.md @@ -4,7 +4,7 @@ title: "Built-in React DOM Hooks" -The `react-dom` package contains Hooks that are only supported for web applications (which run in the browser DOM environment). These Hooks are not supported in non-browser environments like iOS, Android, or Windows applications. If you are looking for Hooks that are supported in web browsers *and other environments* see [the React Hooks page](/reference/react). This page lists all the Hooks in the `react-dom` package. +The `react-dom` package contains Hooks that are only supported for web applications (which run in the browser DOM environment). These Hooks are not supported in non-browser environments like iOS, Android, or Windows applications. If you are looking for Hooks that are supported in web browsers *and other environments* see [the React Hooks page](/reference/react/hooks). This page lists all the Hooks in the `react-dom` package. From 896a689aa18b3fe2736d2066ef917c81e7bdc77c Mon Sep 17 00:00:00 2001 From: Ricky Date: Thu, 16 Oct 2025 17:08:00 -0400 Subject: [PATCH 15/64] Remove ReactConf notes in blogs (#8082) --- ...what-we-have-been-working-on-february-2024.md | 8 -------- ...ct-labs-view-transitions-activity-and-more.md | 16 ++++++++-------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/content/blog/2024/02/15/react-labs-what-we-have-been-working-on-february-2024.md b/src/content/blog/2024/02/15/react-labs-what-we-have-been-working-on-february-2024.md index 9ec330e6b..c3ab47fad 100644 --- a/src/content/blog/2024/02/15/react-labs-what-we-have-been-working-on-february-2024.md +++ b/src/content/blog/2024/02/15/react-labs-what-we-have-been-working-on-february-2024.md @@ -15,14 +15,6 @@ In React Labs posts, we write about projects in active research and development. - - -React Conf 2024 is scheduled for May 15–16 in Henderson, Nevada! If you’re interested in attending React Conf in person, you can [sign up for the ticket lottery](https://forms.reform.app/bLaLeE/react-conf-2024-ticket-lottery/1aRQLK) until February 28th. - -For more info on tickets, free streaming, sponsoring, and more, see [the React Conf website](https://conf.react.dev). - - - --- ## React Compiler {/*react-compiler*/} diff --git a/src/content/blog/2025/04/23/react-labs-view-transitions-activity-and-more.md b/src/content/blog/2025/04/23/react-labs-view-transitions-activity-and-more.md index cdc8f353f..5e9be2255 100644 --- a/src/content/blog/2025/04/23/react-labs-view-transitions-activity-and-more.md +++ b/src/content/blog/2025/04/23/react-labs-view-transitions-activity-and-more.md @@ -16,14 +16,6 @@ In React Labs posts, we write about projects in active research and development. - - -React Conf 2025 is scheduled for October 7–8 in Henderson, Nevada! - -Watch the livestream on [the React Conf website](https://conf.react.dev). - - - Today, we're excited to release documentation for two new experimental features that are ready for testing: - [View Transitions](#view-transitions) @@ -40,6 +32,14 @@ We're also sharing updates on new features currently in development: # New Experimental Features {/*new-experimental-features*/} + + +`` has shipped in `react@19.2`. + +`` and `addTransitionType` are now available in `react@canary`. + + + View Transitions and Activity are now ready for testing in `react@experimental`. These features have been tested in production and are stable, but the final API may still change as we incorporate feedback. You can try them by upgrading React packages to the most recent experimental version: From fe87df57f8121c7f9c61247525441776b6f456bb Mon Sep 17 00:00:00 2001 From: 0xPxt <107792863+0xPxt@users.noreply.github.com> Date: Thu, 16 Oct 2025 23:28:10 +0200 Subject: [PATCH 16/64] clarify SRP definition (#8008) * clarify SRP definition * Update src/content/learn/thinking-in-react.md --------- Co-authored-by: Ricky --- src/content/learn/thinking-in-react.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/thinking-in-react.md b/src/content/learn/thinking-in-react.md index 822891e60..216a381b5 100644 --- a/src/content/learn/thinking-in-react.md +++ b/src/content/learn/thinking-in-react.md @@ -37,7 +37,7 @@ Start by drawing boxes around every component and subcomponent in the mockup and Depending on your background, you can think about splitting up a design into components in different ways: -* **Programming**--use the same techniques for deciding if you should create a new function or object. One such technique is the [single responsibility principle](https://en.wikipedia.org/wiki/Single_responsibility_principle), that is, a component should ideally only do one thing. If it ends up growing, it should be decomposed into smaller subcomponents. +* **Programming**--use the same techniques for deciding if you should create a new function or object. One such technique is the [separation of concerns](https://en.wikipedia.org/wiki/Separation_of_concerns), that is, a component should ideally only be concerned with one thing. If it ends up growing, it should be decomposed into smaller subcomponents. * **CSS**--consider what you would make class selectors for. (However, components are a bit less granular.) * **Design**--consider how you would organize the design's layers. From 7ecf008d84d12ee1e56638804fa657ad7c67b446 Mon Sep 17 00:00:00 2001 From: Matt Carroll <7158882+mattcarrollcode@users.noreply.github.com> Date: Thu, 16 Oct 2025 14:30:54 -0700 Subject: [PATCH 17/64] Add React Conf 2025 recap blog post (#8079) --- src/components/Layout/Page.tsx | 4 +- .../blog/2025/10/16/react-conf-2025-recap.md | 133 ++++++++++++++++++ src/content/blog/index.md | 6 + src/sidebarBlog.json | 7 + 4 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 src/content/blog/2025/10/16/react-conf-2025-recap.md diff --git a/src/components/Layout/Page.tsx b/src/components/Layout/Page.tsx index 89c25f46f..aa39fe5fc 100644 --- a/src/components/Layout/Page.tsx +++ b/src/components/Layout/Page.tsx @@ -15,7 +15,7 @@ import {useRouter} from 'next/router'; import {SidebarNav} from './SidebarNav'; import {Footer} from './Footer'; import {Toc} from './Toc'; -import SocialBanner from '../SocialBanner'; +// import SocialBanner from '../SocialBanner'; import {DocsPageFooter} from 'components/DocsFooter'; import {Seo} from 'components/Seo'; import PageHeading from 'components/PageHeading'; @@ -142,7 +142,7 @@ export function Page({ /> )} - + {/* */} + +Last week we hosted React Conf 2025 where we announced the [React Foundation](/blog/2025/10/07/introducing-the-react-foundation) and showcased new features coming to React and React Native. + + + +--- + +React Conf 2025 was held on October 7-8, 2025, in Henderson, Nevada. + +The entire [day 1](https://www.youtube.com/watch?v=zyVRg2QR6LA&t=1067s) and [day 2](https://www.youtube.com/watch?v=p9OcztRyDl0&t=2299s) streams are available online, and you can view photos from the event [here](https://conf.react.dev/photos). + +In this post, we'll summarize the talks and announcements from the event. + + +## Day 1 Keynote {/*day-1-keynote*/} + +_Watch the full day 1 stream [here.](https://www.youtube.com/watch?v=zyVRg2QR6LA&t=1067s)_ + +In the day 1 keynote, Joe Savona shared the updates from the team and community since the last React Conf and highlights from React 19.0 and 19.1. + +Mofei Zhang highlighted the new features in React 19.2 including: +* [``](https://react.dev/reference/react/Activity) — a new component to manage visibility. +* [`useEffectEvent`](https://react.dev/reference/react/useEffectEvent) to fire events from Effects. +* [Performance Tracks](https://react.dev/reference/dev-tools/react-performance-tracks) — a new profiling tool in DevTools. +* [Partial Pre-Rendering](https://react.dev/blog/2025/10/01/react-19-2#partial-pre-rendering) to pre-render part of an app ahead of time, and resume rendering it later. + +Jack Pope announced new features in Canary including: + +* [``](https://react.dev/reference/react/ViewTransition) — a new component to animate page transitions. +* [Fragment Refs](https://react.dev/reference/react/Fragment#fragmentinstance) — a new way to interact with the DOM nodes wrapped by a Fragment. + +Lauren Tan announced [React Compiler v1.0](https://react.dev/blog/2025/10/07/react-compiler-1) and recommended all apps use React Compiler for benefits like: +* [Automatic memoization](/learn/react-compiler/introduction#what-does-react-compiler-do) that understands React code. +* [New lint rules](/learn/react-compiler/installation#eslint-integration) powered by React Compiler to teach best practices. +* [Default support](/learn/react-compiler/installation#basic-setup) for new apps in Vite, Next.js, and Expo. +* [Migration guides](/learn/react-compiler/incremental-adoption) for existing apps migrating to React Compiler. + +Finally, Seth Webster announced the [React Foundation](/blog/2025/10/07/introducing-the-react-foundation) to steward React's open source development and community. + +Watch day 1 here: + + + +## Day 2 Keynote {/*day-2-keynote*/} + +_Watch the full day 2 stream [here.](https://www.youtube.com/watch?v=p9OcztRyDl0&t=2299s)_ + +Jorge Cohen and Nicola Corti kicked off day 2 highlighting React Native’s incredible growth with 4M weekly downloads (100% growth YoY), and some notable app migrations from Shopify, Zalando, and HelloFresh, award-winning apps like RISE, RUNNA, and Partyful, and AI apps from Mistral, Replit, and v0. + +Riccardo Cipolleschi shared two major announcements for React Native: +- [React Native 0.82 will be New Architecture only](https://reactnative.dev/blog/2025/10/08/react-native-0.82#new-architecture-only) +- [Experimental Hermes V1 support](https://reactnative.dev/blog/2025/10/08/react-native-0.82#experimental-hermes-v1) + +Ruben Norte and Alex Hunt finished out the keynote by announcing: +- [New web-aligned DOM APIs](https://reactnative.dev/blog/2025/10/08/react-native-0.82#dom-node-apis) for improved compatibility with React on the web. +- [New Performance APIs](https://reactnative.dev/blog/2025/10/08/react-native-0.82#web-performance-apis-canary) with a new network panel and desktop app. + +Watch day 2 here: + + + + +## React team talks {/*react-team-talks*/} + +Throughout the conference, there were talks from the React team including: +* [Async React Part I](https://www.youtube.com/watch?v=zyVRg2QR6LA&t=10907s) and [Part II](https://www.youtube.com/watch?v=p9OcztRyDl0&t=29073s) [(Ricky Hanlon)](https://x.com/rickhanlonii) showed what's possible using the last 10 years of innovation. +* [Exploring React Performance](https://www.youtube.com/watch?v=zyVRg2QR6LA&t=20274s) [(Joe Savona)](https://x.com/en_js) showed the results of our React performance research. +* [Reimagining Lists in React Native](https://www.youtube.com/watch?v=p9OcztRyDl0&t=10382s) [(Luna Wei)](https://x.com/lunaleaps) introduced Virtual View, a new primitive for lists that manages visibility with mode-based rendering (hidden/pre-render/visible). +* [Profiling with React Performance tracks](https://www.youtube.com/watch?v=zyVRg2QR6LA&t=8276s) [(Ruslan Lesiutin)](https://x.com/ruslanlesiutin) showed how to use the new React Performance Tracks to debug performance issues and build great apps. +* [React Strict DOM](https://www.youtube.com/watch?v=p9OcztRyDl0&t=9026s) [(Nicolas Gallagher)](https://nicolasgallagher.com/) talked about Meta's approach to using web code on native. +* [View Transitions and Activity](https://www.youtube.com/watch?v=zyVRg2QR6LA&t=4870s) [(Chance Strickland)](https://x.com/chancethedev) — Chance worked with the React team to showcase how to use `` and `` to build fast, native-feeling animations. +* [In case you missed the memo](https://www.youtube.com/watch?v=zyVRg2QR6LA&t=9525s) [(Cody Olsen)](https://bsky.app/profile/codey.bsky.social) - Cody worked with the React team to adopt the Compiler at Sanity Studio, and shared how it went. +## React framework talks {/*react-framework-talks*/} + +The second half of day 2 had a series of talks from React Framework teams including: + +* [React Native, Amplified](https://www.youtube.com/watch?v=p9OcztRyDl0&t=5737s) by [Giovanni Laquidara](https://x.com/giolaq) and [Eric Fahsl](https://x.com/efahsl). +* [React Everywhere: Bringing React Into Native Apps](https://www.youtube.com/watch?v=p9OcztRyDl0&t=18213s) by [Mike Grabowski](https://x.com/grabbou). +* [How Parcel Bundles React Server Components](https://www.youtube.com/watch?v=p9OcztRyDl0&t=19538s) by [Devon Govett](https://x.com/devonovett). +* [Designing Page Transitions](https://www.youtube.com/watch?v=p9OcztRyDl0&t=20640s) by [Delba de Oliveira](https://x.com/delba_oliveira). +* [Build Fast, Deploy Faster — Expo in 2025](https://www.youtube.com/watch?v=p9OcztRyDl0&t=21350s) by [Evan Bacon](https://x.com/baconbrix). +* [The React Router's take on RSC](https://www.youtube.com/watch?v=p9OcztRyDl0&t=22367s) by [Kent C. Dodds](https://x.com/kentcdodds). +* [RedwoodSDK: Web Standards Meet Full-Stack React](https://www.youtube.com/watch?v=p9OcztRyDl0&t=24992s) by [Peter Pistorius](https://x.com/appfactory) and [Aurora Scharff](https://x.com/aurorascharff). +* [TanStack Start](https://www.youtube.com/watch?v=p9OcztRyDl0&t=26065s) by [Tanner Linsley](https://x.com/tannerlinsley). + +## Q&A {/*q-and-a*/} +There were three Q&A panels during the conference: + +* [React Team at Meta Q&A](https://www.youtube.com/watch?v=zyVRg2QR6LA&t=26304s) hosted by [Shruti Kapoor](https://x.com/shrutikapoor08) +* [React Frameworks Q&A](https://www.youtube.com/watch?v=p9OcztRyDl0&t=26812s) hosted by [Jack Herrington](https://x.com/jherr) +* [React and AI Panel](https://www.youtube.com/watch?v=zyVRg2QR6LA&t=18741s) hosted by [Lee Robinson](https://x.com/leerob) + +## And more... {/*and-more*/} + +We also heard talks from the community including: +* [Building an MCP Server](https://www.youtube.com/watch?v=zyVRg2QR6LA&t=24204s) by [James Swinton](https://x.com/JamesSwintonDev) ([AG Grid](https://www.ag-grid.com/?utm_source=react-conf&utm_medium=react-conf-homepage&utm_campaign=react-conf-sponsorship-2025)) +* [Modern Emails using React](https://www.youtube.com/watch?v=zyVRg2QR6LA&t=25521s) by [Zeno Rocha](https://x.com/zenorocha) ([Resend](https://resend.com/)) +* [Why React Native Apps Make All the Money](https://www.youtube.com/watch?v=zyVRg2QR6LA&t=24917s) by [Perttu Lähteenlahti](https://x.com/plahteenlahti) ([RevenueCat](https://www.revenuecat.com/)) +* [The invisible craft of great UX](https://www.youtube.com/watch?v=zyVRg2QR6LA&t=23400s) by [Michał Dudak](https://x.com/michaldudak) ([MUI](https://mui.com/)) + +## Thanks {/*thanks*/} + +Thank you to all the staff, speakers, and participants, who made React Conf 2025 possible. There are too many to list, but we want to thank a few in particular. + +Thank you to [Matt Carroll](https://x.com/mattcarrollcode) for planning the entire event and building the conference website. + +Thank you to [Michael Chan](https://x.com/chantastic) for MCing React Conf with incredible dedication and energy, delivering thoughtful speaker intros, fun jokes, and genuine enthusiasm throughout the event. Thank you to [Jorge Cohen](https://x.com/JorgeWritesCode) for hosting the livestream, interviewing each speaker, and bringing the in-person React Conf experience online. + +Thank you to [Mateusz Kornacki](https://x.com/mat_kornacki), [Mike Grabowski](https://x.com/grabbou), [Kris Lis](https://www.linkedin.com/in/krzysztoflisakakris/) and the team at [Callstack](https://www.callstack.com/) for co-organizing React Conf and providing design, engineering, and marketing support. Thank you to the [ZeroSlope team](https://zeroslopeevents.com/contact-us/): Sunny Leggett, Tracey Harrison, Tara Larish, Whitney Pogue, and Brianne Smythia for helping to organize the event. + +Thank you to [Jorge Cabiedes Acosta](https://github.com/jorge-cab), [Gijs Weterings](https://x.com/gweterings), [Tim Yung](https://x.com/yungsters), and [Jason Bonta](https://x.com/someextent) for bringing questions from the Discord to the livestream. Thank you to [Lynn Yu](https://github.com/lynnshaoyu) for leading the moderation of the Discord. Thank you to [Seth Webster](https://x.com/sethwebster) for welcoming us each day; and to [Christopher Chedeau](https://x.com/vjeux), [Kevin Gozali](https://x.com/fkgozali), and [Pieter De Baets](https://x.com/Javache) for joining us with a special message during the after-party. + +Thank you to [Kadi Kraman](https://x.com/kadikraman), [Beto](https://x.com/betomoedano) and [Nicolas Solerieu](https://www.linkedin.com/in/nicolas-solerieu/) for building the conference mobile app. Thank you [Wojtek Szafraniec](https://x.com/wojteg1337) for help with the conference website. Thank you to [Mustache](https://www.mustachepower.com/) & [Cornerstone](https://cornerstoneav.com/) for the visuals, stage, and sound; and to the Westin Hotel for hosting us. + +Thank you to all the sponsors who made the event possible: [Amazon](https://www.developer.amazon.com), [MUI](https://mui.com/), [Vercel](https://vercel.com/), [Expo](https://expo.dev/), [RedwoodSDK](https://rwsdk.com), [Ag Grid](https://www.ag-grid.com), [RevenueCat](https://www.revenuecat.com/), [Resend](https://resend.com), [Mux](https://www.mux.com/), [Old Mission](https://www.oldmissioncapital.com/), [Arcjet](https://arcjet.com), [Infinite Red](https://infinite.red/), and [RenderATL](https://renderatl.com). + +Thank you to all the speakers who shared their knowledge and experience with the community. + +Finally, thank you to everyone who attended in person and online to show what makes React, React. React is more than a library, it is a community, and it was inspiring to see everyone come together to share and learn together. + +See you next time! diff --git a/src/content/blog/index.md b/src/content/blog/index.md index a30542275..10d277909 100644 --- a/src/content/blog/index.md +++ b/src/content/blog/index.md @@ -12,6 +12,12 @@ You can also follow the [@react.dev](https://bsky.app/profile/react.dev) account
+ + +Last week we hosted React Conf 2025. In this post, we summarize the talks and announcements from the event... + + + We're releasing the compiler's first stable release today, plus linting and tooling improvements to make adoption easier. diff --git a/src/sidebarBlog.json b/src/sidebarBlog.json index be88c3b4a..56aa0ee2c 100644 --- a/src/sidebarBlog.json +++ b/src/sidebarBlog.json @@ -11,6 +11,13 @@ "path": "/blog", "skipBreadcrumb": true, "routes": [ + { + "title": "React Conf 2025 Recap", + "titleForHomepage": "React Conf 2025 Recap", + "icon": "blog", + "date": "October 16, 2025", + "path": "/blog/2025/10/16/react-conf-2025-recap" + }, { "title": "React Compiler v1.0", "titleForHomepage": "React Compiler v1.0", From f8c81a0f4f8e454c850f0c854ad054b32313345c Mon Sep 17 00:00:00 2001 From: Jack Pope Date: Sat, 18 Oct 2025 13:14:02 -0400 Subject: [PATCH 18/64] Use stable activity imports (#8085) --- .../react-labs-view-transitions-activity-and-more.md | 4 ++-- src/content/reference/react/Activity.md | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/content/blog/2025/04/23/react-labs-view-transitions-activity-and-more.md b/src/content/blog/2025/04/23/react-labs-view-transitions-activity-and-more.md index 5e9be2255..9b6095f8b 100644 --- a/src/content/blog/2025/04/23/react-labs-view-transitions-activity-and-more.md +++ b/src/content/blog/2025/04/23/react-labs-view-transitions-activity-and-more.md @@ -11543,7 +11543,7 @@ Try searching for a video, selecting it, and clicking "back": ```js src/App.js -import { ViewTransition } from "react"; import Details from "./Details"; import Home from "./Home"; import { useRouter } from "./router"; import { unstable_Activity, Activity as ActivityStable} from 'react'; let Activity = ActivityStable ?? unstable_Activity; +import { Activity, ViewTransition } from "react"; import Details from "./Details"; import Home from "./Home"; import { useRouter } from "./router"; export default function App() { const { url } = useRouter(); @@ -12880,7 +12880,7 @@ With this update, if the content on the next page has time to pre-render, it wil ```js src/App.js -import { ViewTransition, use } from "react"; import Details from "./Details"; import Home from "./Home"; import { useRouter } from "./router"; import {fetchVideos} from './data'; import { unstable_Activity, Activity as ActivityStable} from 'react'; let Activity = ActivityStable ?? unstable_Activity; +import { Activity, ViewTransition, use } from "react"; import Details from "./Details"; import Home from "./Home"; import { useRouter } from "./router"; import {fetchVideos} from './data'; export default function App() { const { url } = useRouter(); diff --git a/src/content/reference/react/Activity.md b/src/content/reference/react/Activity.md index 53c38f64f..b53064c2b 100644 --- a/src/content/reference/react/Activity.md +++ b/src/content/reference/react/Activity.md @@ -190,7 +190,7 @@ and check out the new behavior: ```js src/App.js active -import { useState } from 'react'; import { unstable_Activity, Activity as ActivityStable} from 'react'; let Activity = ActivityStable ?? unstable_Activity; +import { Activity, useState } from 'react'; import Sidebar from './Sidebar.js'; @@ -376,7 +376,7 @@ If we switch to using an Activity boundary to show and hide the active tab, we c ```js src/App.js active -import { useState } from 'react'; import { unstable_Activity, Activity as ActivityStable} from 'react'; let Activity = ActivityStable ?? unstable_Activity; +import { Activity, useState } from 'react'; import TabButton from './TabButton.js'; import Home from './Home.js'; import Contact from './Contact.js'; @@ -620,7 +620,7 @@ Try clicking the Posts tab now: ```js src/App.js -import { useState, Suspense } from 'react'; import { unstable_Activity, Activity as ActivityStable} from 'react'; let Activity = ActivityStable ?? unstable_Activity; +import { Activity, useState, Suspense } from 'react'; import TabButton from './TabButton.js'; import Home from './Home.js'; import Posts from './Posts.js'; @@ -1010,7 +1010,7 @@ Let's update `App` to hide the inactive tab with a hidden Activity boundary inst ```js src/App.js active -import { useState } from 'react'; import { unstable_Activity, Activity as ActivityStable} from 'react'; let Activity = ActivityStable ?? unstable_Activity; +import { Activity, useState } from 'react'; import TabButton from './TabButton.js'; import Home from './Home.js'; import Video from './Video.js'; @@ -1127,7 +1127,7 @@ Let's see the new behavior. Try playing the video, switching to the Home tab, th ```js src/App.js active -import { useState } from 'react'; import { unstable_Activity, Activity as ActivityStable} from 'react'; let Activity = ActivityStable ?? unstable_Activity; +import { Activity, useState } from 'react'; import TabButton from './TabButton.js'; import Home from './Home.js'; import Video from './Video.js'; From 4b0935b8c119d03278f709681c63ad8a940b22b5 Mon Sep 17 00:00:00 2001 From: Jordan Thomson Date: Mon, 20 Oct 2025 23:15:38 +1100 Subject: [PATCH 19/64] Add `` bullet to built-in components section (#8087) --- src/content/reference/react/components.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/content/reference/react/components.md b/src/content/reference/react/components.md index 7ce3fab63..081f206c0 100644 --- a/src/content/reference/react/components.md +++ b/src/content/reference/react/components.md @@ -16,6 +16,7 @@ React exposes a few built-in components that you can use in your JSX. * [``](/reference/react/Profiler) lets you measure rendering performance of a React tree programmatically. * [``](/reference/react/Suspense) lets you display a fallback while the child components are loading. * [``](/reference/react/StrictMode) enables extra development-only checks that help you find bugs early. +* [``](/reference/react/Activity) lets you hide and restore the UI and internal state of its children. --- From 2c7798dcc51fbd07ebe41f49e5ded4839a029f72 Mon Sep 17 00:00:00 2001 From: lauren Date: Mon, 20 Oct 2025 13:31:58 -0400 Subject: [PATCH 20/64] Fix typo in react compiler blog post date (#8091) Fix a small typo --- src/sidebarBlog.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sidebarBlog.json b/src/sidebarBlog.json index 56aa0ee2c..7bcd4a000 100644 --- a/src/sidebarBlog.json +++ b/src/sidebarBlog.json @@ -22,7 +22,7 @@ "title": "React Compiler v1.0", "titleForHomepage": "React Compiler v1.0", "icon": "blog", - "date": "October 8, 2025", + "date": "October 7, 2025", "path": "/blog/2025/10/07/react-compiler-1" }, { From c0af2d01cba44225dece12fa9e71476ce30a4af3 Mon Sep 17 00:00:00 2001 From: Johanna Kveton Date: Wed, 29 Oct 2025 19:49:24 +0100 Subject: [PATCH 21/64] Add note on error boundary limitations (#8108) --- src/content/reference/react/Component.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/content/reference/react/Component.md b/src/content/reference/react/Component.md index 9d2d1007b..2509aa759 100644 --- a/src/content/reference/react/Component.md +++ b/src/content/reference/react/Component.md @@ -1271,6 +1271,16 @@ We recommend defining components as functions instead of classes. [See how to mi By default, if your application throws an error during rendering, React will remove its UI from the screen. To prevent this, you can wrap a part of your UI into an *Error Boundary*. An Error Boundary is a special component that lets you display some fallback UI instead of the part that crashed--for example, an error message. + +Error boundaries do not catch errors for: + +- Event handlers [(learn more)](/learn/responding-to-events) +- [Server side rendering](/reference/react-dom/server) +- Errors thrown in the error boundary itself (rather than its children) +- Asynchronous code (e.g. `setTimeout` or `requestAnimationFrame` callbacks); an exception is the usage of the [`startTransition`](/reference/react/useTransition#starttransition) function returned by the [`useTransition`](/reference/react/useTransition) Hook. Errors thrown inside the transition function are caught by error boundaries [(learn more)](/reference/react/useTransition#displaying-an-error-to-users-with-error-boundary) + + + To implement an Error Boundary component, you need to provide [`static getDerivedStateFromError`](#static-getderivedstatefromerror) which lets you update state in response to an error and display an error message to the user. You can also optionally implement [`componentDidCatch`](#componentdidcatch) to add some extra logic, for example, to log the error to an analytics service. With [`captureOwnerStack`](/reference/react/captureOwnerStack) you can include the Owner Stack during development. From e57e9122852b5c64129dd71b5beb1e982be6708d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9E=84=EC=8A=B9=EC=A7=84?= Date: Fri, 31 Oct 2025 20:04:05 +0900 Subject: [PATCH 22/64] docs(blog): Add 'React 19.2' to blog sidebar (#8113) --- src/sidebarBlog.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/sidebarBlog.json b/src/sidebarBlog.json index 7bcd4a000..3497fdd0b 100644 --- a/src/sidebarBlog.json +++ b/src/sidebarBlog.json @@ -32,6 +32,13 @@ "date": "October 7, 2025", "path": "/blog/2025/10/07/introducing-the-react-foundation" }, + { + "title": "React 19.2", + "titleForHomepage": "React 19.2", + "icon": "blog", + "date": "October 1, 2025", + "path": "/blog/2025/10/01/react-19-2" + }, { "title": "React Labs: View Transitions, Activity, and more", "titleForHomepage": "View Transitions and Activity", From f9e2c1396769bb5da87db60f9ff03683d18711e2 Mon Sep 17 00:00:00 2001 From: Joshua Comeau Date: Sat, 1 Nov 2025 00:11:49 -0400 Subject: [PATCH 23/64] Remove 'esquery' hack to potentially enable Turbopack (#8115) * Remove esquery hack * Add comment explaining next.config change --- next.config.js | 8 ++++++++ src/components/MDX/Sandpack/runESLint.tsx | 7 ------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/next.config.js b/next.config.js index 5a5755307..fe88a09a0 100644 --- a/next.config.js +++ b/next.config.js @@ -36,6 +36,14 @@ const nextConfig = { // Don't bundle the shim unnecessarily. config.resolve.alias['use-sync-external-store/shim'] = 'react'; + // ESLint depends on the CommonJS version of esquery, + // but Webpack loads the ESM version by default. This + // alias ensures the correct version is used. + // + // More info: + // https://github.com/reactjs/react.dev/pull/8115 + config.resolve.alias['esquery'] = 'esquery/dist/esquery.min.js'; + const {IgnorePlugin, NormalModuleReplacementPlugin} = require('webpack'); config.plugins.push( new NormalModuleReplacementPlugin( diff --git a/src/components/MDX/Sandpack/runESLint.tsx b/src/components/MDX/Sandpack/runESLint.tsx index a0b835461..667b22d7e 100644 --- a/src/components/MDX/Sandpack/runESLint.tsx +++ b/src/components/MDX/Sandpack/runESLint.tsx @@ -21,13 +21,6 @@ const getCodeMirrorPosition = ( const linter = new Linter(); -// HACK! Eslint requires 'esquery' using `require`, but there's no commonjs interop. -// because of this it tries to run `esquery.parse()`, while there's only `esquery.default.parse()`. -// This hack places the functions in the right place. -const esquery = require('esquery'); -esquery.parse = esquery.default?.parse; -esquery.matches = esquery.default?.matches; - const reactRules = require('eslint-plugin-react-hooks').rules; linter.defineRules({ 'react-hooks/rules-of-hooks': reactRules['rules-of-hooks'], From f020b53d8b06e0890d9167dd13f966e72e525e46 Mon Sep 17 00:00:00 2001 From: martin rebo Date: Wed, 5 Nov 2025 10:39:59 +0100 Subject: [PATCH 24/64] docs: add missing 'Static APIs' link to React DOM reference page (#8127) --- src/content/reference/react/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/content/reference/react/index.md b/src/content/reference/react/index.md index ccba58a06..7693a4cff 100644 --- a/src/content/reference/react/index.md +++ b/src/content/reference/react/index.md @@ -28,6 +28,7 @@ React-dom contains features that are only supported for web applications (which * [APIs](/reference/react-dom) - The `react-dom` package contains methods supported only in web applications. * [Client APIs](/reference/react-dom/client) - The `react-dom/client` APIs let you render React components on the client (in the browser). * [Server APIs](/reference/react-dom/server) - The `react-dom/server` APIs let you render React components to HTML on the server. +* [Static APIs](/reference/react-dom/static) - The `react-dom/static` APIs let you generate static HTML for React components. ## React Compiler {/*react-compiler*/} From 5c632dc8fb4f37e9968f1b3e3ace580bfed6e7db Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 5 Nov 2025 18:41:50 +0900 Subject: [PATCH 25/64] Nit: wording --- src/content/reference/react/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/reference/react/index.md b/src/content/reference/react/index.md index 7693a4cff..bdb202157 100644 --- a/src/content/reference/react/index.md +++ b/src/content/reference/react/index.md @@ -21,7 +21,7 @@ Programmatic React features: ## React DOM {/*react-dom*/} -React-dom contains features that are only supported for web applications (which run in the browser DOM environment). This section is broken into the following: +React DOM contains features that are only supported for web applications (which run in the browser DOM environment). This section is broken into the following: * [Hooks](/reference/react-dom/hooks) - Hooks for web applications which run in the browser DOM environment. * [Components](/reference/react-dom/components) - React supports all of the browser built-in HTML and SVG components. From 9c0763d38a9475dd77dd479ab83547e20f050cf5 Mon Sep 17 00:00:00 2001 From: Hichem Date: Wed, 5 Nov 2025 22:11:14 +0100 Subject: [PATCH 26/64] fix: correct links for Redwood and TanStack (#8121) * fix: correct link for RedwoodJS to RedwoodSDK in documentation * fix: update links for React Query and TanStack Start in documentation * fix: update Vite installation command to use TypeScript template * fix: update references from React Query to TanStack Query in documentation --- src/content/blog/2024/05/22/react-conf-2024-recap.md | 2 +- src/content/blog/2025/02/14/sunsetting-create-react-app.md | 2 +- src/content/learn/build-a-react-app-from-scratch.md | 4 ++-- src/content/learn/creating-a-react-app.md | 4 ++-- src/content/learn/synchronizing-with-effects.md | 2 +- .../eslint-plugin-react-hooks/lints/rules-of-hooks.md | 2 +- src/content/reference/react/useEffect.md | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/content/blog/2024/05/22/react-conf-2024-recap.md b/src/content/blog/2024/05/22/react-conf-2024-recap.md index 7cb7d42ee..e22464010 100644 --- a/src/content/blog/2024/05/22/react-conf-2024-recap.md +++ b/src/content/blog/2024/05/22/react-conf-2024-recap.md @@ -112,7 +112,7 @@ Thank you [Ricky Hanlon](https://www.youtube.com/watch?v=FxTZL2U-uKg&t=1263s) fo Thank you [Callstack](https://www.callstack.com/) for building the conference website; and to [Kadi Kraman](https://twitter.com/kadikraman) and the [Expo](https://expo.dev/) team for building the conference mobile app. -Thank you to all the sponsors who made the event possible: [Remix](https://remix.run/), [Amazon](https://developer.amazon.com/apps-and-games?cmp=US_2024_05_3P_React-Conf-2024&ch=prtnr&chlast=prtnr&pub=ref&publast=ref&type=org&typelast=org), [MUI](https://mui.com/), [Sentry](https://sentry.io/for/react/?utm_source=sponsored-conf&utm_medium=sponsored-event&utm_campaign=frontend-fy25q2-evergreen&utm_content=logo-reactconf2024-learnmore), [Abbott](https://www.jobs.abbott/software), [Expo](https://expo.dev/), [RedwoodJS](https://redwoodjs.com/), and [Vercel](https://vercel.com). +Thank you to all the sponsors who made the event possible: [Remix](https://remix.run/), [Amazon](https://developer.amazon.com/apps-and-games?cmp=US_2024_05_3P_React-Conf-2024&ch=prtnr&chlast=prtnr&pub=ref&publast=ref&type=org&typelast=org), [MUI](https://mui.com/), [Sentry](https://sentry.io/for/react/?utm_source=sponsored-conf&utm_medium=sponsored-event&utm_campaign=frontend-fy25q2-evergreen&utm_content=logo-reactconf2024-learnmore), [Abbott](https://www.jobs.abbott/software), [Expo](https://expo.dev/), [RedwoodJS](https://rwsdk.com/), and [Vercel](https://vercel.com). Thank you to the AV Team for the visuals, stage, and sound; and to the Westin Hotel for hosting us. diff --git a/src/content/blog/2025/02/14/sunsetting-create-react-app.md b/src/content/blog/2025/02/14/sunsetting-create-react-app.md index 9ced6231c..6f3e95d81 100644 --- a/src/content/blog/2025/02/14/sunsetting-create-react-app.md +++ b/src/content/blog/2025/02/14/sunsetting-create-react-app.md @@ -177,7 +177,7 @@ export default function Dashboard() { } ``` -Fetching in an effect means the user has to wait longer to see the content, even though the data could have been fetched earlier. To solve this, you can use a data fetching library like [React Query](https://react-query.tanstack.com/), [SWR](https://swr.vercel.app/), [Apollo](https://www.apollographql.com/docs/react), or [Relay](https://relay.dev/) which provide options to prefetch data so the request is started before the component renders. +Fetching in an effect means the user has to wait longer to see the content, even though the data could have been fetched earlier. To solve this, you can use a data fetching library like [TanStack Query](https://tanstack.com/query/), [SWR](https://swr.vercel.app/), [Apollo](https://www.apollographql.com/docs/react), or [Relay](https://relay.dev/) which provide options to prefetch data so the request is started before the component renders. These libraries work best when integrated with your routing "loader" pattern to specify data dependencies at the route level, which allows the router to optimize your data fetches: diff --git a/src/content/learn/build-a-react-app-from-scratch.md b/src/content/learn/build-a-react-app-from-scratch.md index 185b693b1..c74fa9afd 100644 --- a/src/content/learn/build-a-react-app-from-scratch.md +++ b/src/content/learn/build-a-react-app-from-scratch.md @@ -34,7 +34,7 @@ The first step is to install a build tool like `vite`, `parcel`, or `rsbuild`. T [Vite](https://vite.dev/) is a build tool that aims to provide a faster and leaner development experience for modern web projects. -{`npm create vite@latest my-app -- --template react`} +{`npm create vite@latest my-app -- --template react-ts`} Vite is opinionated and comes with sensible defaults out of the box. Vite has a rich ecosystem of plugins to support fast refresh, JSX, Babel/SWC, and other common features. See Vite's [React plugin](https://vite.dev/plugins/#vitejs-plugin-react) or [React SWC plugin](https://vite.dev/plugins/#vitejs-plugin-react-swc) and [React SSR example project](https://vite.dev/guide/ssr.html#example-projects) to get started. @@ -97,7 +97,7 @@ Note that fetching data directly in components can lead to slower loading times If you're fetching data from most backends or REST-style APIs, we suggest using: -- [React Query](https://react-query.tanstack.com/) +- [TanStack Query](https://tanstack.com/query/) - [SWR](https://swr.vercel.app/) - [RTK Query](https://redux-toolkit.js.org/rtk-query/overview) diff --git a/src/content/learn/creating-a-react-app.md b/src/content/learn/creating-a-react-app.md index df512cca8..a65b59f6e 100644 --- a/src/content/learn/creating-a-react-app.md +++ b/src/content/learn/creating-a-react-app.md @@ -63,8 +63,8 @@ Expo is maintained by [Expo (the company)](https://expo.dev/about). Building app There are other up-and-coming frameworks that are working towards our full stack React vision: -- [TanStack Start (Beta)](https://tanstack.com/): TanStack Start is a full-stack React framework powered by TanStack Router. It provides a full-document SSR, streaming, server functions, bundling, and more using tools like Nitro and Vite. -- [RedwoodJS](https://redwoodjs.com/): Redwood is a full stack React framework with lots of pre-installed packages and configuration that makes it easy to build full-stack web applications. +- [TanStack Start (Beta)](https://tanstack.com/start/): TanStack Start is a full-stack React framework powered by TanStack Router. It provides a full-document SSR, streaming, server functions, bundling, and more using tools like Nitro and Vite. +- [RedwoodSDK](https://rwsdk.com/): Redwood is a full stack React framework with lots of pre-installed packages and configuration that makes it easy to build full-stack web applications. diff --git a/src/content/learn/synchronizing-with-effects.md b/src/content/learn/synchronizing-with-effects.md index 7f61a255b..fa27f8d8f 100644 --- a/src/content/learn/synchronizing-with-effects.md +++ b/src/content/learn/synchronizing-with-effects.md @@ -733,7 +733,7 @@ Writing `fetch` calls inside Effects is a [popular way to fetch data](https://ww This list of downsides is not specific to React. It applies to fetching data on mount with any library. Like with routing, data fetching is not trivial to do well, so we recommend the following approaches: - **If you use a [framework](/learn/start-a-new-react-project#full-stack-frameworks), use its built-in data fetching mechanism.** Modern React frameworks have integrated data fetching mechanisms that are efficient and don't suffer from the above pitfalls. -- **Otherwise, consider using or building a client-side cache.** Popular open source solutions include [React Query](https://tanstack.com/query/latest), [useSWR](https://swr.vercel.app/), and [React Router 6.4+.](https://beta.reactrouter.com/en/main/start/overview) You can build your own solution too, in which case you would use Effects under the hood, but add logic for deduplicating requests, caching responses, and avoiding network waterfalls (by preloading data or hoisting data requirements to routes). +- **Otherwise, consider using or building a client-side cache.** Popular open source solutions include [TanStack Query](https://tanstack.com/query/latest), [useSWR](https://swr.vercel.app/), and [React Router 6.4+.](https://beta.reactrouter.com/en/main/start/overview) You can build your own solution too, in which case you would use Effects under the hood, but add logic for deduplicating requests, caching responses, and avoiding network waterfalls (by preloading data or hoisting data requirements to routes). You can continue fetching data directly in Effects if neither of these approaches suit you. diff --git a/src/content/reference/eslint-plugin-react-hooks/lints/rules-of-hooks.md b/src/content/reference/eslint-plugin-react-hooks/lints/rules-of-hooks.md index 56a9d74be..a364ab67f 100644 --- a/src/content/reference/eslint-plugin-react-hooks/lints/rules-of-hooks.md +++ b/src/content/reference/eslint-plugin-react-hooks/lints/rules-of-hooks.md @@ -132,7 +132,7 @@ useEffect(() => { -There are better ways to fetch data rather than in a useEffect. Consider using React Query, useSWR, or React Router 6.4+ for data fetching. These solutions handle deduplicating requests, caching responses, and avoiding network waterfalls. +There are better ways to fetch data rather than in a useEffect. Consider using TanStack Query, useSWR, or React Router 6.4+ for data fetching. These solutions handle deduplicating requests, caching responses, and avoiding network waterfalls. Learn more: [Fetching Data](/learn/synchronizing-with-effects#fetching-data) diff --git a/src/content/reference/react/useEffect.md b/src/content/reference/react/useEffect.md index 413e3ebc4..f67f56eda 100644 --- a/src/content/reference/react/useEffect.md +++ b/src/content/reference/react/useEffect.md @@ -1050,7 +1050,7 @@ Writing `fetch` calls inside Effects is a [popular way to fetch data](https://ww This list of downsides is not specific to React. It applies to fetching data on mount with any library. Like with routing, data fetching is not trivial to do well, so we recommend the following approaches: - **If you use a [framework](/learn/start-a-new-react-project#full-stack-frameworks), use its built-in data fetching mechanism.** Modern React frameworks have integrated data fetching mechanisms that are efficient and don't suffer from the above pitfalls. -- **Otherwise, consider using or building a client-side cache.** Popular open source solutions include [React Query](https://tanstack.com/query/latest/), [useSWR](https://swr.vercel.app/), and [React Router 6.4+.](https://beta.reactrouter.com/en/main/start/overview) You can build your own solution too, in which case you would use Effects under the hood but also add logic for deduplicating requests, caching responses, and avoiding network waterfalls (by preloading data or hoisting data requirements to routes). +- **Otherwise, consider using or building a client-side cache.** Popular open source solutions include [TanStack Query](https://tanstack.com/query/latest/), [useSWR](https://swr.vercel.app/), and [React Router 6.4+.](https://beta.reactrouter.com/en/main/start/overview) You can build your own solution too, in which case you would use Effects under the hood but also add logic for deduplicating requests, caching responses, and avoiding network waterfalls (by preloading data or hoisting data requirements to routes). You can continue fetching data directly in Effects if neither of these approaches suit you. From abd1fe01db79041db08d2a3e2bde32c11ad47171 Mon Sep 17 00:00:00 2001 From: WuMingDao <146366930+WuMingDao@users.noreply.github.com> Date: Thu, 6 Nov 2025 05:39:44 +0800 Subject: [PATCH 27/64] =?UTF-8?q?docs:=20Remove=20redundant=20symbols=20?= =?UTF-8?q?=E2=80=98=20=E2=80=9C=20=E2=80=99=20(#8101)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/content/reference/react/act.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/reference/react/act.md b/src/content/reference/react/act.md index eff3f891f..7e1273e3d 100644 --- a/src/content/reference/react/act.md +++ b/src/content/reference/react/act.md @@ -152,7 +152,7 @@ Don’t forget that dispatching DOM events only works when the DOM container is ## Troubleshooting {/*troubleshooting*/} -### I'm getting an error: "The current testing environment is not configured to support act"(...)" {/*error-the-current-testing-environment-is-not-configured-to-support-act*/} +### I'm getting an error: "The current testing environment is not configured to support act(...)" {/*error-the-current-testing-environment-is-not-configured-to-support-act*/} Using `act` requires setting `global.IS_REACT_ACT_ENVIRONMENT=true` in your test environment. This is to ensure that `act` is only used in the correct environment. From 6a708898a695fc4af8d854101464aa02a4befae8 Mon Sep 17 00:00:00 2001 From: Emmanuel Valentin Date: Wed, 5 Nov 2025 16:21:05 -0600 Subject: [PATCH 28/64] Fix typo in childIds array in initialTravelPlan (#8112) --- src/content/learn/choosing-the-state-structure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/choosing-the-state-structure.md b/src/content/learn/choosing-the-state-structure.md index 5be2b4d34..f6ed669ab 100644 --- a/src/content/learn/choosing-the-state-structure.md +++ b/src/content/learn/choosing-the-state-structure.md @@ -1716,7 +1716,7 @@ export const initialTravelPlan = { 34: { id: 34, title: 'Oceania', - childIds: [35, 36, 37, 38, 39, 40,, 41], + childIds: [35, 36, 37, 38, 39, 40, 41], }, 35: { id: 35, From d271a7ac11d2bf0d6e95ebdfacaf1038421f9be0 Mon Sep 17 00:00:00 2001 From: PaulyBearCoding <180776718+PaulyBearCoding@users.noreply.github.com> Date: Wed, 5 Nov 2025 18:25:46 -0800 Subject: [PATCH 29/64] Fix incorrect condition in "Chains of computations" example (#8109) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #8097 The refactored example in the "Chains of computations" section uses an incorrect condition that changes the game logic from the original. The original Effect-based code advances the round after 4 gold cards: - Increments first (0→1, 1→2, 2→3, 3→4) - Then checks `goldCardCount > 3` (true when count is 4) The refactored code with `goldCardCount <= 3` allows 5 gold cards: - Checks before incrementing - Allows counts 0, 1, 2, 3 to increment (4 values) - Advances on the 5th card (when count is 4) This fix changes the condition to `goldCardCount < 3`: - Allows counts 0, 1, 2 to increment (3 values) - Advances on the 4th card (when count is 3) - Matches the original behavior Verified by tracing execution logic and building the docs site locally. Co-authored-by: PaulyBearCoding --- src/content/learn/you-might-not-need-an-effect.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md index 76e58e307..73be0b171 100644 --- a/src/content/learn/you-might-not-need-an-effect.md +++ b/src/content/learn/you-might-not-need-an-effect.md @@ -437,7 +437,7 @@ function Game() { // ✅ Calculate all the next state in the event handler setCard(nextCard); if (nextCard.gold) { - if (goldCardCount <= 3) { + if (goldCardCount < 3) { setGoldCardCount(goldCardCount + 1); } else { setGoldCardCount(0); From b440d6698f6e21d56a78b10f625bd23191183588 Mon Sep 17 00:00:00 2001 From: Oke Kehinde <55279370+okeken@users.noreply.github.com> Date: Mon, 10 Nov 2025 19:22:50 +0000 Subject: [PATCH 30/64] fix(links): update internal links (#8136) --- .github/ISSUE_TEMPLATE/3-framework.yml | 4 ++-- src/components/Layout/HomeContent.js | 2 +- .../react-labs-what-we-have-been-working-on-march-2023.md | 4 ++-- src/content/blog/2024/12/05/react-19.md | 2 +- src/content/learn/add-react-to-an-existing-project.md | 4 ++-- src/content/learn/synchronizing-with-effects.md | 2 +- src/content/learn/typescript.md | 2 +- src/content/learn/you-might-not-need-an-effect.md | 4 ++-- src/content/learn/your-first-component.md | 2 +- src/content/reference/react-dom/client/createRoot.md | 2 +- src/content/reference/react-dom/client/index.md | 2 +- src/content/reference/react-dom/index.md | 2 +- src/content/reference/react-dom/preinit.md | 2 +- src/content/reference/react-dom/preinitModule.md | 2 +- src/content/reference/react-dom/preload.md | 2 +- src/content/reference/react-dom/preloadModule.md | 2 +- src/content/reference/react-dom/server/index.md | 2 +- src/content/reference/react-dom/static/index.md | 2 +- src/content/reference/react/useEffect.md | 6 +++--- src/content/reference/rsc/directives.md | 2 +- src/content/reference/rsc/use-client.md | 2 +- 21 files changed, 27 insertions(+), 27 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/3-framework.yml b/.github/ISSUE_TEMPLATE/3-framework.yml index a47295e1e..87f03a660 100644 --- a/.github/ISSUE_TEMPLATE/3-framework.yml +++ b/.github/ISSUE_TEMPLATE/3-framework.yml @@ -8,11 +8,11 @@ body: value: | ## Apply to be included as a recommended React framework - _This form is for framework authors to apply to be included as a recommended [React framework](https://react.dev/learn/start-a-new-react-project). If you are not a framework author, please contact the authors before submitting._ + _This form is for framework authors to apply to be included as a recommended [React framework](https://react.dev/learn/creating-a-react-app). If you are not a framework author, please contact the authors before submitting._ Our goal when recommending a framework is to start developers with a React project that solves common problems like code splitting, data fetching, routing, and HTML generation without any extra work later. We believe this will allow users to get started quickly with React, and scale their app to production. - While we understand that many frameworks may want to be featured, this page is not a place to advertise every possible React framework or all frameworks that you can add React to. There are many great frameworks that offer support for React that are not listed in our guides. The frameworks we recommend have invested significantly in the React ecosystem, and collaborated with the React team to be compatible with our [full-stack React architecture vision](https://react.dev/learn/start-a-new-react-project#which-features-make-up-the-react-teams-full-stack-architecture-vision). + While we understand that many frameworks may want to be featured, this page is not a place to advertise every possible React framework or all frameworks that you can add React to. There are many great frameworks that offer support for React that are not listed in our guides. The frameworks we recommend have invested significantly in the React ecosystem, and collaborated with the React team to be compatible with our [full-stack React architecture vision](https://react.dev/learn/creating-a-react-app#which-features-make-up-the-react-teams-full-stack-architecture-vision). To be included, frameworks must meet the following criteria: diff --git a/src/components/Layout/HomeContent.js b/src/components/Layout/HomeContent.js index 9cc26bdaa..f9b785db4 100644 --- a/src/components/Layout/HomeContent.js +++ b/src/components/Layout/HomeContent.js @@ -270,7 +270,7 @@ export function HomeContent() { + href="/learn/creating-a-react-app"> Get started with a framework
diff --git a/src/content/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023.md b/src/content/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023.md index 1bc78149d..df1fd085d 100644 --- a/src/content/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023.md +++ b/src/content/blog/2023/03/22/react-labs-what-we-have-been-working-on-march-2023.md @@ -31,7 +31,7 @@ The biggest change is that we introduced [`async` / `await`](https://github.com/ Now that we have data fetching pretty well sorted, we're exploring the other direction: sending data from the client to the server, so that you can execute database mutations and implement forms. We're doing this by letting you pass Server Action functions across the server/client boundary, which the client can then call, providing seamless RPC. Server Actions also give you progressively enhanced forms before JavaScript loads. -React Server Components has shipped in [Next.js App Router](/learn/start-a-new-react-project#nextjs-app-router). This showcases a deep integration of a router that really buys into RSC as a primitive, but it's not the only way to build a RSC-compatible router and framework. There's a clear separation for features provided by the RSC spec and implementation. React Server Components is meant as a spec for components that work across compatible React frameworks. +React Server Components has shipped in [Next.js App Router](/learn/creating-a-react-app#nextjs-app-router). This showcases a deep integration of a router that really buys into RSC as a primitive, but it's not the only way to build a RSC-compatible router and framework. There's a clear separation for features provided by the RSC spec and implementation. React Server Components is meant as a spec for components that work across compatible React frameworks. We generally recommend using an existing framework, but if you need to build your own custom framework, it is possible. Building your own RSC-compatible framework is not as easy as we'd like it to be, mainly due to the deep bundler integration needed. The current generation of bundlers are great for use on the client, but they weren't designed with first-class support for splitting a single module graph between the server and the client. This is why we're now partnering directly with bundler developers to get the primitives for RSC built-in. @@ -92,7 +92,7 @@ Since our last update, we've tested an experimental version of prerendering inte ## Transition Tracing {/*transition-tracing*/} -The Transition Tracing API lets you detect when [React Transitions](/reference/react/useTransition) become slower and investigate why they may be slow. Following our last update, we have completed the initial design of the API and published an [RFC](https://github.com/reactjs/rfcs/pull/238). The basic capabilities have also been implemented. The project is currently on hold. We welcome feedback on the RFC and look forward to resuming its development to provide a better performance measurement tool for React. This will be particularly useful with routers built on top of React Transitions, like the [Next.js App Router](/learn/start-a-new-react-project#nextjs-app-router). +The Transition Tracing API lets you detect when [React Transitions](/reference/react/useTransition) become slower and investigate why they may be slow. Following our last update, we have completed the initial design of the API and published an [RFC](https://github.com/reactjs/rfcs/pull/238). The basic capabilities have also been implemented. The project is currently on hold. We welcome feedback on the RFC and look forward to resuming its development to provide a better performance measurement tool for React. This will be particularly useful with routers built on top of React Transitions, like the [Next.js App Router](/learn/creating-a-react-app#nextjs-app-router). * * * In addition to this update, our team has made recent guest appearances on community podcasts and livestreams to speak more on our work and answer questions. diff --git a/src/content/blog/2024/12/05/react-19.md b/src/content/blog/2024/12/05/react-19.md index 65bf42757..4e9aad8e8 100644 --- a/src/content/blog/2024/12/05/react-19.md +++ b/src/content/blog/2024/12/05/react-19.md @@ -355,7 +355,7 @@ For more information, see [React DOM Static APIs](/reference/react-dom/static). Server Components are a new option that allows rendering components ahead of time, before bundling, in an environment separate from your client application or SSR server. This separate environment is the "server" in React Server Components. Server Components can run once at build time on your CI server, or they can be run for each request using a web server. -React 19 includes all of the React Server Components features included from the Canary channel. This means libraries that ship with Server Components can now target React 19 as a peer dependency with a `react-server` [export condition](https://github.com/reactjs/rfcs/blob/main/text/0227-server-module-conventions.md#react-server-conditional-exports) for use in frameworks that support the [Full-stack React Architecture](/learn/start-a-new-react-project#which-features-make-up-the-react-teams-full-stack-architecture-vision). +React 19 includes all of the React Server Components features included from the Canary channel. This means libraries that ship with Server Components can now target React 19 as a peer dependency with a `react-server` [export condition](https://github.com/reactjs/rfcs/blob/main/text/0227-server-module-conventions.md#react-server-conditional-exports) for use in frameworks that support the [Full-stack React Architecture](/learn/creating-a-react-app#which-features-make-up-the-react-teams-full-stack-architecture-vision). diff --git a/src/content/learn/add-react-to-an-existing-project.md b/src/content/learn/add-react-to-an-existing-project.md index 5d3d44005..f98bece42 100644 --- a/src/content/learn/add-react-to-an-existing-project.md +++ b/src/content/learn/add-react-to-an-existing-project.md @@ -20,7 +20,7 @@ Let's say you have an existing web app at `example.com` built with another serve Here's how we recommend to set it up: -1. **Build the React part of your app** using one of the [React-based frameworks](/learn/start-a-new-react-project). +1. **Build the React part of your app** using one of the [React-based frameworks](/learn/creating-a-react-app). 2. **Specify `/some-app` as the *base path*** in your framework's configuration (here's how: [Next.js](https://nextjs.org/docs/app/api-reference/config/next-config-js/basePath), [Gatsby](https://www.gatsbyjs.com/docs/how-to/previews-deploys-hosting/path-prefix/)). 3. **Configure your server or a proxy** so that all requests under `/some-app/` are handled by your React app. @@ -149,7 +149,7 @@ root.render(); Notice how the original HTML content from `index.html` is preserved, but your own `NavigationBar` React component now appears inside the ` -
- -
diff --git a/src/components/Layout/TopNav/TopNav.tsx b/src/components/Layout/TopNav/TopNav.tsx index 148098933..efc90ed2c 100644 --- a/src/components/Layout/TopNav/TopNav.tsx +++ b/src/components/Layout/TopNav/TopNav.tsx @@ -29,7 +29,6 @@ import {IconHamburger} from 'components/Icon/IconHamburger'; import {IconSearch} from 'components/Icon/IconSearch'; import {Search} from 'components/Search'; import {Logo} from '../../Logo'; -import {Feedback} from '../Feedback'; import {SidebarRouteTree} from '../Sidebar'; import type {RouteItem} from '../getRouteMeta'; import {siteConfig} from 'siteConfig'; @@ -448,9 +447,6 @@ export default function TopNav({
-
- -
)} diff --git a/src/styles/index.css b/src/styles/index.css index 6b2915be4..7bdf4c765 100644 --- a/src/styles/index.css +++ b/src/styles/index.css @@ -741,13 +741,6 @@ ol.mdx-illustration-block { } } -.exit { - opacity: 0; - transition: opacity 500ms ease-out; - transition-delay: 1s; - pointer-events: none; -} - .uwu-visible { display: none; } From a2a19bae5f3ea54496915979fcfd01a9738d07c3 Mon Sep 17 00:00:00 2001 From: Joseph Date: Wed, 28 Jan 2026 21:48:01 +0100 Subject: [PATCH 56/64] feat: Add Accept header content negotiation for markdown (#8272) --- next.config.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/next.config.js b/next.config.js index c9dc3ead8..7580eb944 100644 --- a/next.config.js +++ b/next.config.js @@ -21,6 +21,20 @@ const nextConfig = { }, async rewrites() { return [ + // Serve markdown when Accept header prefers text/markdown + // Useful for LLM agents - https://www.skeptrune.com/posts/use-the-accept-header-to-serve-markdown-instead-of-html-to-llms/ + { + source: '/:path*', + has: [ + { + type: 'header', + key: 'accept', + value: '(.*text/markdown.*)', + }, + ], + destination: '/api/md/:path*', + }, + // Explicit .md extension also serves markdown { source: '/:path*.md', destination: '/api/md/:path*', From ec13a90a368d7eb64fca34b96bd595f7e9c4c595 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yadiel=20V=C3=A9lez?= <16180439+hernan-yadiel@users.noreply.github.com> Date: Thu, 29 Jan 2026 11:23:10 -0500 Subject: [PATCH 57/64] remove outdated note about streaming ssr (#8277) --- src/content/reference/react/ViewTransition.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/content/reference/react/ViewTransition.md b/src/content/reference/react/ViewTransition.md index acf59ac38..9f451eddc 100644 --- a/src/content/reference/react/ViewTransition.md +++ b/src/content/reference/react/ViewTransition.md @@ -1052,8 +1052,6 @@ Just like any Transition, React waits for data and new CSS (` @@ -18,24 +18,18 @@ title: useOptimistic ## Reference {/*reference*/} -### `useOptimistic(state, updateFn)` {/*use*/} +### `useOptimistic(value, reducer?)` {/*useoptimistic*/} -`useOptimistic` is a React Hook that lets you show a different state while an async action is underway. It accepts some state as an argument and returns a copy of that state that can be different during the duration of an async action such as a network request. You provide a function that takes the current state and the input to the action, and returns the optimistic state to be used while the action is pending. - -This state is called the "optimistic" state because it is usually used to immediately present the user with the result of performing an action, even though the action actually takes time to complete. +Call `useOptimistic` at the top level of your component to create optimistic state for a value. ```js import { useOptimistic } from 'react'; -function AppContainer() { - const [optimisticState, addOptimistic] = useOptimistic( - state, - // updateFn - (currentState, optimisticValue) => { - // merge and return new state - // with optimistic value - } - ); +function MyComponent({name, todos}) { + const [optimisticAge, setOptimisticAge] = useOptimistic(28); + const [optimisticName, setOptimisticName] = useOptimistic(name); + const [optimisticTodos, setOptimisticTodos] = useOptimistic(todos, todoReducer); + // ... } ``` @@ -43,89 +37,1047 @@ function AppContainer() { #### Parameters {/*parameters*/} -* `state`: the value to be returned initially and whenever no action is pending. -* `updateFn(currentState, optimisticValue)`: a function that takes the current state and the optimistic value passed to `addOptimistic` and returns the resulting optimistic state. It must be a pure function. `updateFn` takes in two parameters. The `currentState` and the `optimisticValue`. The return value will be the merged value of the `currentState` and `optimisticValue`. - +* `value`: The value returned when there are no pending Actions. +* **optional** `reducer(currentState, action)`: The reducer function that specifies how the optimistic state gets updated. It must be pure, should take the current state and reducer action arguments, and should return the next optimistic state. #### Returns {/*returns*/} -* `optimisticState`: The resulting optimistic state. It is equal to `state` unless an action is pending, in which case it is equal to the value returned by `updateFn`. -* `addOptimistic`: `addOptimistic` is the dispatching function to call when you have an optimistic update. It takes one argument, `optimisticValue`, of any type and will call the `updateFn` with `state` and `optimisticValue`. +`useOptimistic` returns an array with exactly two values: + +1. `optimisticState`: The current optimistic state. It is equal to `value` unless an Action is pending, in which case it is equal to the state returned by `reducer` (or the value passed to the set function if no `reducer` was provided). +2. The [`set` function](#setoptimistic) that lets you update the optimistic state to a different value inside an Action. + +--- + +### `set` functions, like `setOptimistic(optimisticState)` {/*setoptimistic*/} + +The `set` function returned by `useOptimistic` lets you update the state for the duration of an [Action](reference/react/useTransition#functions-called-in-starttransition-are-called-actions). You can pass the next state directly, or a function that calculates it from the previous state: + +```js +const [optimisticLike, setOptimisticLike] = useOptimistic(false); +const [optimisticSubs, setOptimisticSubs] = useOptimistic(subs); + +function handleClick() { + startTransition(async () => { + setOptimisticLike(true); + setOptimisticSubs(a => a + 1); + await saveChanges(); + }); +} +``` + +#### Parameters {/*setoptimistic-parameters*/} + +* `optimisticState`: The value that you want the optimistic state to be during an [Action](reference/react/useTransition#functions-called-in-starttransition-are-called-actions). If you provided a `reducer` to `useOptimistic`, this value will be passed as the second argument to your reducer. It can be a value of any type. + * If you pass a function as `optimisticState`, it will be treated as an _updater function_. It must be pure, should take the pending state as its only argument, and should return the next optimistic state. React will put your updater function in a queue and re-render your component. During the next render, React will calculate the next state by applying the queued updaters to the previous state similar to [`useState` updaters](/reference/react/useState#setstate-parameters). + +#### Returns {/*setoptimistic-returns*/} + +`set` functions do not have a return value. + +#### Caveats {/*setoptimistic-caveats*/} + +* The `set` function must be called inside an [Action](reference/react/useTransition#functions-called-in-starttransition-are-called-actions). If you call the setter outside an Action, [React will show a warning](#an-optimistic-state-update-occurred-outside-a-transition-or-action) and the optimistic state will briefly render. + + + +#### How optimistic state works {/*how-optimistic-state-works*/} + +`useOptimistic` lets you show a temporary value while a Action is in progress: + +```js +const [value, setValue] = useState('a'); +const [optimistic, setOptimistic] = useOptimistic(value); + +startTransition(async () => { + setOptimistic('b'); + const newValue = await saveChanges('b'); + setValue(newValue); +}); +``` + +When the setter is called inside an Action, `useOptimistic` will trigger a re-render to show that state while the Action is in progress. Otherwise, the `value` passed to `useOptimistic` is returned. + +This state is called the "optimistic" because it is used to immediately present the user with the result of performing an Action, even though the Action actually takes time to complete. + +**How the update flows** + +1. **Update immediately**: When `setOptimistic('b')` is called, React immediately renders with `'b'`. + +2. **(Optional) await in Action**: If you await in the Action, React continues showing `'b'`. + +3. **Transition scheduled**: `setValue(newValue)` schedules an update to the real state. + +4. **(Optional) wait for Suspense**: If `newValue` suspends, React continues showing `'b'`. + +5. **Single render commit**: Finally, the `newValue` is commits for `value` and `optimistic`. + +There's no extra render to "clear" the optimistic state. The optimistic and real state converge in the same render when the Transition completes. + + + +#### Optimistic state is temporary {/*optimistic-state-is-temporary*/} + +Optimistic state is only renders while an Action is in progress, otherwise `value` is rendered. + +If `saveChanges` returned `'c'`, then both `value` and `optimistic` will be `'c'`, not `'b'`. + + + +**How the final state is determined** + +The `value` argument to `useOptimistic` determines what displays after the Action finishes. How this works depends on the pattern you use: + +- **Hardcoded values** like `useOptimistic(false)`: After the Action, `state` is still `false`, so the UI shows `false`. This is useful for pending states where you always start from `false`. + +- **Props or state passed in** like `useOptimistic(isLiked)`: If the parent updates `isLiked` during the Action, the new value is used after the Action completes. This is how the UI reflects the result of the Action. + +- **Reducer pattern** like `useOptimistic(items, fn)`: If `items` changes while the Action is pending, React re-runs your `reducer` with the new `items` to recalculate the state. This keeps your optimistic additions on top of the latest data. + +**What happens when the Action fails** + +If the Action throws an error, the Transition still ends, and React renders with whatever `value` currently is. Since the parent typically only updates `value` on success, a failure means `value` hasn't changed, so the UI shows what it showed before the optimistic update. You can catch the error to show a message to the user. + + --- ## Usage {/*usage*/} -### Optimistically updating forms {/*optimistically-updating-with-forms*/} +### Adding optimistic state to a component {/*adding-optimistic-state-to-a-component*/} + +Call `useOptimistic` at the top level of your component to declare one or more optimistic states. + +```js [[1, 4, "age"], [1, 5, "name"], [1, 6, "todos"], [2, 4, "optimisticAge"], [2, 5, "optimisticName"], [2, 6, "optimisticTodos"], [3, 4, "setOptimisticAge"], [3, 5, "setOptimisticName"], [3, 6, "setOptimisticTodos"], [4, 6, "reducer"]] +import { useOptimistic } from 'react'; + +function MyComponent({age, name, todos}) { + const [optimisticAge, setOptimisticAge] = useOptimistic(age); + const [optimisticName, setOptimisticName] = useOptimistic(name); + const [optimisticTodos, setOptimisticTodos] = useOptimistic(todos, reducer); + // ... +``` + +`useOptimistic` returns an array with exactly two items: + +1. The optimistic state, initially set to the value provided. +2. The set function that lets you temporarily change the state during an [Action](reference/react/useTransition#functions-called-in-starttransition-are-called-actions). + * If a reducer is provided, it will run before returning the optimistic state. + +To use the optimistic state, call the `set` function inside an Action. + +Actions are functions called inside `startTransition`: + +```js {3} +function onAgeChange(e) { + startTransition(async () => { + setOptimisticAge(42); + const newAge = await postAge(42); + setAge(newAge); + }); +} +``` + +React will render the optimistic state `42` first while the `age` remains the current age. The Action waits for POST, and then renders the `newAge` for both `age` and `optimisticAge`. + +See [How optimistic state works](#how-optimistic-state-works) for a deep dive. + + + +When using [Action props](/reference/react/useTransition#exposing-action-props-from-components), you can call the set function without `startTransition`: + +```js [[3, 2, "setOptimisticName"]] +async function submitAction() { + setOptimisticName('Taylor'); + await updateName('Taylor'); +} +``` + +This works because Action props are already called inside `startTransition`. + +For an example, see: [Using optimistic state in Action props](#using-optimistic-state-in-action-props). + + + +--- + +### Using optimistic state in Action props {/*using-optimistic-state-in-action-props*/} + +In an [Action prop](/reference/react/useTransition#exposing-action-props-from-components), you can call the optimistic setter directly without `startTransition`. + +This example sets optimistic state inside a `
` `submitAction` prop: + + + +```js src/App.js +import { useState, startTransition } from 'react'; +import EditName from './EditName'; + +export default function App() { + const [name, setName] = useState('Alice'); + + return ; +} +``` + +```js src/EditName.js active +import { useOptimistic, startTransition } from 'react'; +import { updateName } from './actions.js'; + +export default function EditName({ name, action }) { + const [optimisticName, setOptimisticName] = useOptimistic(name); + + async function submitAction(formData) { + const newName = formData.get('name'); + setOptimisticName(newName); + + const updatedName = await updateName(newName); + startTransition(() => { + action(updatedName); + }) + } + + return ( + +

Your name is: {optimisticName}

+

+ + +

+ + ); +} +``` + +```js src/actions.js hidden +export async function updateName(name) { + await new Promise((res) => setTimeout(res, 1000)); + return name; +} +``` + +
+ +In this example, when the user submits the form, the `optimisticName` updates immediately to show the `newName` optimistically while the server request is in progress. When the request completes, `name` and `optimisticName` are rendered with the actual `updatedName` from the response. + + + +#### Why doesn't this need `startTransition`? {/*why-doesnt-this-need-starttransition*/} + +By convention, props called inside `startTransition` are named with "Action". -The `useOptimistic` Hook provides a way to optimistically update the user interface before a background operation, like a network request, completes. In the context of forms, this technique helps to make apps feel more responsive. When a user submits a form, instead of waiting for the server's response to reflect the changes, the interface is immediately updated with the expected outcome. +Since `submitAction` is named with "Action", you know it's already called inside `startTransition`. -For example, when a user types a message into the form and hits the "Send" button, the `useOptimistic` Hook allows the message to immediately appear in the list with a "Sending..." label, even before the message is actually sent to a server. This "optimistic" approach gives the impression of speed and responsiveness. The form then attempts to truly send the message in the background. Once the server confirms the message has been received, the "Sending..." label is removed. +See [Exposing `action` prop from components](/reference/react/useTransition#exposing-action-props-from-components) for the Action prop pattern. + + + +--- + +### Adding optimistic state to Action props {/*adding-optimistic-state-to-action-props*/} + +When creating an [Action prop](/reference/react/useTransition#exposing-action-props-from-components), you can add `useOptimistic` to show immediate feedback. + +Here's a button that shows "Submitting..." while the `action` is pending: +```js src/App.js +import { useState, startTransition } from 'react'; +import Button from './Button'; +import { submitForm } from './actions.js'; + +export default function App() { + const [count, setCount] = useState(0); + return ( +
+ + {count > 0 &&

Submitted {count}!

} +
+ ); +} +``` + +```js src/Button.js active +import { useOptimistic, startTransition } from 'react'; + +export default function Button({ action, children }) { + const [isPending, setIsPending] = useOptimistic(false); + + return ( + + ); +} +``` + +```js src/actions.js hidden +export async function submitForm() { + await new Promise((res) => setTimeout(res, 1000)); +} +``` + +
+ +When the button is clicked, `setIsPending(true)` uses optimistic state to immediately show "Submitting..." and disable the button. When the Action is done, `isPending` is rendered as `false` automatically. + +This pattern automatically shows a pending state however `action` prop is used with `Button`: + +```js +// Show pending state for a state update + + ); +} +``` + +```js src/actions.js hidden +export async function toggleLike(value) { + return await new Promise((res) => setTimeout(() => res(value), 1000)); + // In a real app, this would update the server +} +``` + +```js src/index.js hidden +import React from 'react'; +import {createRoot} from 'react-dom/client'; +import './styles.css'; + +import App from './App'; + +const root = createRoot(document.getElementById('root')); +// Not using StrictMode so double render logs are not shown. +root.render(); +``` + + + +When the button is clicked, `setOptimisticIsLiked` immediately updates the displayed state to show the heart as liked. Meanwhile, `await toggleLike` runs in the background. When the `await` completes, `setIsLiked` parent updates the "real" `isLiked` state, and the optimistic state is rendered to match this new value. + + + +This example reads from `optimisticIsLiked` to calculate the next value. This works when the base state won't change, but if the base state might change while your Action is pending, you may want to use a state updater or the reducer. + +See [Updating state based on the current state](#updating-state-based-on-current-state) for an example. + + + +--- + +### Updating multiple values together {/*updating-multiple-values-together*/} + +When an optimistic update affects multiple related values, use a reducer to update them together. This ensures the UI stays consistent. + +Here's a follow button that updates both the follow state and follower count: + + + +```js src/App.js +import { useState, startTransition } from 'react'; +import { followUser, unfollowUser } from './actions.js'; +import FollowButton from './FollowButton'; + +export default function App() { + const [user, setUser] = useState({ + name: 'React', + isFollowing: false, + followerCount: 10500 + }); + + async function followAction(shouldFollow) { + if (shouldFollow) { + await followUser(user.name); + } else { + await unfollowUser(user.name); + } + startTransition(() => { + setUser(current => ({ + ...current, + isFollowing: shouldFollow, + followerCount: current.followerCount + (shouldFollow ? 1 : -1) + })); + }); + } + + return ; +} +``` + +```js src/FollowButton.js active +import { useOptimistic, startTransition } from 'react'; + +export default function FollowButton({ user, followAction }) { + const [optimisticState, updateOptimistic] = useOptimistic( + { isFollowing: user.isFollowing, followerCount: user.followerCount }, + (current, isFollowing) => ({ + isFollowing, + followerCount: current.followerCount + (isFollowing ? 1 : -1) + }) ); + function handleClick() { + const newFollowState = !optimisticState.isFollowing; + startTransition(async () => { + updateOptimistic(newFollowState); + await followAction(newFollowState); + }); + } + return ( - <> -
- - -
- {optimisticMessages.map((message, index) => ( -
- {message.text} - {!!message.sending && (Sending...)} -
- ))} - - +
+

{user.name}

+

{optimisticState.followerCount} followers

+ +
); } +``` + +```js src/actions.js hidden +export async function followUser(name) { + await new Promise((res) => setTimeout(res, 1000)); +} + +export async function unfollowUser(name) { + await new Promise((res) => setTimeout(res, 1000)); +} +``` + +
+ +The reducer receives the new `isFollowing` value and calculates both the new follow state and the updated follower count in a single update. This ensures the button text and count always stay in sync. + + + + +#### Choosing between updaters and reducers {/*choosing-between-updaters-and-reducers*/} + +`useOptimistic` supports two patterns for calculating state based on current state: + +**Updater functions** work like [useState updaters](/reference/react/useState#updating-state-based-on-the-previous-state). Pass a function to the setter: + +```js +const [optimistic, setOptimistic] = useOptimistic(value); +setOptimistic(current => !current); +``` + +**Reducers** separate the update logic from the setter call: + +```js +const [optimistic, dispatch] = useOptimistic(value, (current, action) => { + // Calculate next state based on current and action +}); +dispatch(action); +``` + +**Use updaters** for calculations where the setter call naturally describes the update. This is similar to using `setState(prev => ...)` with `useState`. + +**Use reducers** when you need to pass data to the update (like which item to add) or when handling multiple types of updates with a single hook. + +**Why use a reducer?** + +Reducers are essential when the base state might change while your Transition is pending. If `todos` changes while your add is pending (for example, another user added a todo), React will re-run your reducer with the new `todos` to recalculate what to show. This ensures your new todo is added to the latest list, not an outdated copy. + +An updater function like `setOptimistic(prev => [...prev, newItem])` would only see the state from when the Transition started, missing any updates that happened during the async work. + + + +--- + +### Optimistically adding to a list {/*optimistically-adding-to-a-list*/} + +When you need to optimistically add items to a list, use a `reducer`: + + + +```js src/App.js +import { useState, startTransition } from 'react'; +import { addTodo } from './actions.js'; +import TodoList from './TodoList'; export default function App() { - const [messages, setMessages] = useState([ - { text: "Hello there!", sending: false, key: 1 } + const [todos, setTodos] = useState([ + { id: 1, text: 'Learn React' } ]); - async function sendMessageAction(formData) { - const sentMessage = await deliverMessage(formData.get("message")); + + async function addTodoAction(newTodo) { + const savedTodo = await addTodo(newTodo); startTransition(() => { - setMessages((messages) => [{ text: sentMessage }, ...messages]); - }) + setTodos(todos => [...todos, savedTodo]); + }); + } + + return ; +} +``` + +```js src/TodoList.js active +import { useOptimistic, startTransition } from 'react'; + +export default function TodoList({ todos, addTodoAction }) { + const [optimisticTodos, addOptimisticTodo] = useOptimistic( + todos, + (currentTodos, newTodo) => [ + ...currentTodos, + { id: newTodo.id, text: newTodo.text, pending: true } + ] + ); + + function handleAddTodo(text) { + const newTodo = { id: crypto.randomUUID(), text: text }; + startTransition(async () => { + addOptimisticTodo(newTodo); + await addTodoAction(newTodo); + }); } - return ; + + return ( +
+ +
    + {optimisticTodos.map(todo => ( +
  • + {todo.text} {todo.pending && "(Adding...)"} +
  • + ))} +
+
+ ); } ``` -```js src/actions.js -export async function deliverMessage(message) { +```js src/actions.js hidden +export async function addTodo(todo) { await new Promise((res) => setTimeout(res, 1000)); - return message; + // In a real app, this would save to the server + return { ...todo, pending: false }; } ``` +
+ +The `reducer` receives the current list of todos and the new todo to add. This is important because if the `todos` prop changes while your add is pending (for example, another user added a todo), React will update your optimistic state by re-running the reducer with the updated list. This ensures your new todo is added to the latest list, not an outdated copy. + + + +Each optimistic item includes a `pending: true` flag so you can show loading state for individual items. When the server responds and the parent updates the canonical `todos` list with the saved item, the optimistic state updates to the confirmed item without the pending flag. + + + +--- + +### Handling multiple `action` types {/*handling-multiple-action-types*/} + +When you need to handle multiple types of optimistic updates (like adding and removing items), use a reducer pattern with `action` objects. + +This shopping cart example shows how to handle add and remove with a single reducer: + + + +```js src/App.js +import { useState, startTransition } from 'react'; +import { addToCart, removeFromCart, updateQuantity } from './actions.js'; +import ShoppingCart from './ShoppingCart'; + +export default function App() { + const [cart, setCart] = useState([]); + + const cartActions = { + async add(item) { + await addToCart(item); + startTransition(() => { + setCart(current => { + const exists = current.find(i => i.id === item.id); + if (exists) { + return current.map(i => + i.id === item.id ? { ...i, quantity: i.quantity + 1 } : i + ); + } + return [...current, { ...item, quantity: 1 }]; + }); + }); + }, + async remove(id) { + await removeFromCart(id); + startTransition(() => { + setCart(current => current.filter(item => item.id !== id)); + }); + }, + async updateQuantity(id, quantity) { + await updateQuantity(id, quantity); + startTransition(() => { + setCart(current => + current.map(item => + item.id === id ? { ...item, quantity } : item + ) + ); + }); + } + }; + + return ; +} +``` + +```js src/ShoppingCart.js active +import { useOptimistic, startTransition } from 'react'; + +export default function ShoppingCart({ cart, cartActions }) { + const [optimisticCart, dispatch] = useOptimistic( + cart, + (currentCart, action) => { + switch (action.type) { + case 'add': + const exists = currentCart.find(item => item.id === action.item.id); + if (exists) { + return currentCart.map(item => + item.id === action.item.id + ? { ...item, quantity: item.quantity + 1, pending: true } + : item + ); + } + return [...currentCart, { ...action.item, quantity: 1, pending: true }]; + case 'remove': + return currentCart.filter(item => item.id !== action.id); + case 'update_quantity': + return currentCart.map(item => + item.id === action.id + ? { ...item, quantity: action.quantity, pending: true } + : item + ); + default: + return currentCart; + } + } + ); + + function handleAdd(item) { + startTransition(async () => { + dispatch({ type: 'add', item }); + await cartActions.add(item); + }); + } + + function handleRemove(id) { + startTransition(async () => { + dispatch({ type: 'remove', id }); + await cartActions.remove(id); + }); + } + + function handleUpdateQuantity(id, quantity) { + startTransition(async () => { + dispatch({ type: 'update_quantity', id, quantity }); + await cartActions.updateQuantity(id, quantity); + }); + } + + const total = optimisticCart.reduce( + (sum, item) => sum + item.price * item.quantity, + 0 + ); + + return ( +
+

Shopping Cart

+
+ {' '} + +
+ {optimisticCart.length === 0 ? ( +

Your cart is empty

+ ) : ( +
    + {optimisticCart.map(item => ( +
  • + {item.name} - ${item.price} × + {item.quantity} + {' '}= ${item.price * item.quantity} + + {item.pending && ' ...'} +
  • + ))} +
+ )} +

Total: ${total}

+
+ ); +} +``` + +```js src/actions.js hidden +export async function addToCart(item) { + await new Promise((res) => setTimeout(res, 800)); +} + +export async function removeFromCart(id) { + await new Promise((res) => setTimeout(res, 800)); +} + +export async function updateQuantity(id, quantity) { + await new Promise((res) => setTimeout(res, 800)); +} +```
+ +The reducer handles three `action` types (`add`, `remove`, `update_quantity`) and returns the new optimistic state for each. Each `action` sets a `pending: true` flag so you can show visual feedback while the [Server Function](/reference/rsc/server-functions) runs. + +--- + +### Optimistic delete with error recovery {/*optimistic-delete-with-error-recovery*/} + +When deleting items optimistically, you should handle the case where the Action fails. + +This example shows how to display an error message when a delete fails, and the UI automatically rolls back to show the item again. + + + +```js src/App.js +import { useState, startTransition } from 'react'; +import { deleteItem } from './actions.js'; +import ItemList from './ItemList'; + +export default function App() { + const [items, setItems] = useState([ + { id: 1, name: 'Learn React' }, + { id: 2, name: 'Build an app' }, + { id: 3, name: 'Deploy to production' }, + ]); + + async function deleteAction(id) { + await deleteItem(id); + startTransition(() => { + setItems(current => current.filter(item => item.id !== id)); + }); + } + + return ; +} +``` + +```js src/ItemList.js active +import { useState, useOptimistic, startTransition } from 'react'; + +export default function ItemList({ items, deleteAction }) { + const [error, setError] = useState(null); + const [optimisticItems, removeItem] = useOptimistic( + items, + (currentItems, idToRemove) => + currentItems.map(item => + item.id === idToRemove + ? { ...item, deleting: true } + : item + ) + ); + + function handleDelete(id) { + setError(null); + startTransition(async () => { + removeItem(id); + try { + await deleteAction(id); + } catch (e) { + setError(e.message); + } + }); + } + + return ( +
+

Your Items

+
    + {optimisticItems.map(item => ( +
  • + {item.name} + +
  • + ))} +
+ {error && ( +

+ {error} +

+ )} +
+ ); +} +``` + +```js src/actions.js hidden +export async function deleteItem(id) { + await new Promise((res) => setTimeout(res, 1000)); + // Item 3 always fails to demonstrate error recovery + if (id === 3) { + throw new Error('Cannot delete. Permission denied.'); + } +} +``` + +
+ +Try deleting 'Deploy to production'. When the delete fails, the item automatically reappears in the list. + +--- + +## Troubleshooting {/*troubleshooting*/} + +### I'm getting an error: "An optimistic state update occurred outside a Transition or Action" {/*an-optimistic-state-update-occurred-outside-a-transition-or-action*/} + +You may see this error: + + + + + +An optimistic state update occurred outside a Transition or Action. To fix, move the update to an Action, or wrap with `startTransition`. + + + + + +The optimistic setter function must be called inside `startTransition`: + +```js +// 🚩 Incorrect: outside a Transition +function handleClick() { + setOptimistic(newValue); // Warning! + // ... +} + +// ✅ Correct: inside a Transition +function handleClick() { + startTransition(async () => { + setOptimistic(newValue); + // ... + }); +} + +// ✅ Also correct: inside an Action prop +function submitAction(formData) { + setOptimistic(newValue); + // ... +} +``` + +When you call the setter outside an Action, the optimistic state will briefly appear and then immediately revert back to the original value. This happens because there's no Transition to "hold" the optimistic state while your Action runs. + +### I'm getting an error: "Cannot update optimistic state while rendering" {/*cannot-update-optimistic-state-while-rendering*/} + +You may see this error: + + + + + +Cannot update optimistic state while rendering. + + + + + +This error occurs when you call the optimistic setter during the render phase of a component. You can only call it from event handlers, effects, or other callbacks: + +```js +// 🚩 Incorrect: calling during render +function MyComponent({ items }) { + const [isPending, setPending] = useOptimistic(false); + + // This runs during render - not allowed! + setPending(true); + + // ... +} + +// ✅ Correct: calling inside startTransition +function MyComponent({ items }) { + const [isPending, setPending] = useOptimistic(false); + + function handleClick() { + startTransition(() => { + setPending(true); + // ... + }); + } + + // ... +} + +// ✅ Also correct: calling from an Action +function MyComponent({ items }) { + const [isPending, setPending] = useOptimistic(false); + + function action() { + setPending(true); + // ... + } + + // ... +} +``` + +### My optimistic updates show stale values {/*my-optimistic-updates-show-stale-values*/} + +If your optimistic state seems to be based on old data, consider using an updater function or reducer to calculate the optimistic state relative to the current state. + +```js +// May show stale data if state changes during Action +const [optimistic, setOptimistic] = useOptimistic(count); +setOptimistic(5); // Always sets to 5, even if count changed + +// Better: relative updates handle state changes correctly +const [optimistic, adjust] = useOptimistic(count, (current, delta) => current + delta); +adjust(1); // Always adds 1 to whatever the current count is +``` + +See [Updating state based on the current state](#updating-state-based-on-current-state) for details. + +### I don't know if my optimistic update is pending {/*i-dont-know-if-my-optimistic-update-is-pending*/} + +To know when `useOptimistic` is pending, you have three options: + +1. **Check if `optimisticValue === value`** + +```js +const [optimistic, setOptimistic] = useOptimistic(value); +const isPending = optimistic !== value; +``` + +If the values are not equal, there's a Transition in progress. + +2. **Add a `useTransition`** + +``` +const [isPending, startTransition] = useTransition(); +const [optimistic, setOptimistic] = useOptimistic(value); + +//... +startTransition(() => { + setOptimistic(state); +}) +``` + +Since `useTransition` uses `useOptimsitic` for `isPending` under the hood, this is equivalent to option 1. + +3**Add a `pending` flag in your reducer** + +```js +const [optimistic, addOptimistic] = useOptimistic( + items, + (state, newItem) => [...state, { ...newItem, isPending: true }] +); +``` From 4c52ab89e58159be4c004c9a8ffd8605a9b4ec28 Mon Sep 17 00:00:00 2001 From: Rhys Evans Date: Fri, 30 Jan 2026 19:53:53 +0000 Subject: [PATCH 60/64] Update separating-events-from-effects.md (#8257) Removed an extraneous "a" from the text --- src/content/learn/separating-events-from-effects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/learn/separating-events-from-effects.md b/src/content/learn/separating-events-from-effects.md index 7903cb363..5f6ce4ee8 100644 --- a/src/content/learn/separating-events-from-effects.md +++ b/src/content/learn/separating-events-from-effects.md @@ -568,7 +568,7 @@ label { display: block; margin-top: 10px; } -You can think of Effect Events as being very similar to event handlers. The main difference is that event handlers run in response to a user interactions, whereas Effect Events are triggered by you from Effects. Effect Events let you "break the chain" between the reactivity of Effects and code that should not be reactive. +You can think of Effect Events as being very similar to event handlers. The main difference is that event handlers run in response to user interactions, whereas Effect Events are triggered by you from Effects. Effect Events let you "break the chain" between the reactivity of Effects and code that should not be reactive. ### Reading latest props and state with Effect Events {/*reading-latest-props-and-state-with-effect-events*/} From 38b52cfdf059b2efc5ee3223a758efe00319fcc7 Mon Sep 17 00:00:00 2001 From: Ricky Date: Fri, 30 Jan 2026 14:54:45 -0500 Subject: [PATCH 61/64] More claude stuff (#8280) * More claude stuff * more stuff from uee edit * revert --- .claude/agents/docs-reviewer.md | 77 +- .claude/docs/react-docs-patterns.md | 637 ------------- .claude/settings.json | 5 + .claude/skills/docs-components/SKILL.md | 414 ++++++++- .claude/skills/docs-sandpack/SKILL.md | 134 ++- .claude/skills/docs-voice/SKILL.md | 137 +++ .claude/skills/docs-writer-blog/SKILL.md | 756 +++++++++++++++ .claude/skills/docs-writer-learn/SKILL.md | 301 +++++- .claude/skills/docs-writer-reference/SKILL.md | 862 +++++++++++++++++- .claude/skills/react-expert/SKILL.md | 335 +++++++ .claude/skills/review-docs/SKILL.md | 20 + .eslintignore | 1 + .gitignore | 1 + 13 files changed, 2879 insertions(+), 801 deletions(-) delete mode 100644 .claude/docs/react-docs-patterns.md create mode 100644 .claude/skills/docs-voice/SKILL.md create mode 100644 .claude/skills/docs-writer-blog/SKILL.md create mode 100644 .claude/skills/react-expert/SKILL.md create mode 100644 .claude/skills/review-docs/SKILL.md diff --git a/.claude/agents/docs-reviewer.md b/.claude/agents/docs-reviewer.md index 6d769cb6f..af0a856e4 100644 --- a/.claude/agents/docs-reviewer.md +++ b/.claude/agents/docs-reviewer.md @@ -1,77 +1,28 @@ --- name: docs-reviewer -description: "Use after editing docs to review changes. Orchestrates docs-writer-learn, docs-writer-reference, docs-components, and docs-sandpack skills to validate structure, components, and style" +description: "Lean docs reviewer that dispatches reviews docs for a particular skill." model: opus color: cyan --- -# React Documentation Reviewer Agent +You are a direct, critical, expert reviewer for React documentation. -You are an expert reviewer for React documentation. Your role is to validate documentation changes for consistency, correctness, and adherence to established patterns. +Your role is to use given skills to validate given doc pages for consistency, correctness, and adherence to established patterns. -## Available Skills +Complete this process: -You have access to specialized skills that define the authoritative patterns for React docs. **Always invoke the relevant skills** to get the current patterns: +## Phase 1: Task Creation +1. CRITICAL: Read the skill requested. +2. Understand the skill's requirements. +3. Create a task list to validate skills requirements. -| Skill | When to Use | -|-------|-------------| -| `docs-writer-learn` | Reviewing files in `src/content/learn/` | -| `docs-writer-reference` | Reviewing files in `src/content/reference/` | -| `docs-components` | Validating MDX components (DeepDive, Pitfall, Note, Recipes, Challenges) | -| `docs-sandpack` | Validating interactive code examples | +## Phase 2: Validate -## Review Process +1. Read the docs files given. +2. Review each file with the task list to verify. -1. **Identify changed files** - Check git status or read the files to review -2. **Determine document type** based on path: - - `src/content/learn/**` → Invoke `docs-writer-learn` - - `src/content/reference/**` → Invoke `docs-writer-reference` -3. **Invoke component skills** for any MDX components or Sandpack examples in the file -4. **Read the patterns reference** at `.claude/docs/react-docs-patterns.md` for comprehensive details -5. **Validate against each skill's requirements** -6. **Run verification commands** -7. **Report issues with specific line numbers and fixes** +## Phase 3: Respond -## Verification Commands +You must respond with a checklist of the issues you identified, and line number. -These commands can help identify issues (user may run manually): - -```bash -yarn lint-heading-ids # Check heading ID format -yarn lint # Check for ESLint issues -yarn deadlinks # Check for broken links -``` - -## Issue Reporting Format - -``` -## Documentation Review Results - -### Errors (must fix) -- **Line 45**: Missing heading ID. Change `## Events` to `## Events {/*events*/}` -- **Line 78**: `` missing `####` heading as first child - -### Warnings (recommended) -- **Line 23**: Capitalize "effect" to "Effect" when referring to the React concept - -### Summary -- Errors: X -- Warnings: Y -- Status: PASS | BLOCKED (fix errors before committing) -``` - -## Key Validation Points - -These are quick checks - see the skills for full details: - -### All Documents -- All `##`, `###`, `####` headings have explicit IDs: `{/*lowercase-with-hyphens*/}` -- React terms capitalized: Hook, Effect, State, Context, Ref, Component -- Uses "you" to address the reader -- No time estimates ("quick", "simple", "easy") -- Internal links use relative paths (`/learn/...`, `/reference/...`) - -### Invoke Skills For -- **Structure validation** → `docs-writer-learn` or `docs-writer-reference` -- **Component usage** → `docs-components` -- **Code examples** → `docs-sandpack` +DO NOT respond with passed validations, ONLY respond with the problems. diff --git a/.claude/docs/react-docs-patterns.md b/.claude/docs/react-docs-patterns.md deleted file mode 100644 index f8df03d0b..000000000 --- a/.claude/docs/react-docs-patterns.md +++ /dev/null @@ -1,637 +0,0 @@ -# React Documentation Patterns Reference - -Comprehensive reference for React documentation patterns. Use this when writing or reviewing docs. - ---- - -## Document Templates - -### Learn Page Template (`src/content/learn/`) - -```mdx ---- -title: Your Page Title ---- - - - -Opening paragraph introducing the topic. Use *italics* for new terms being defined. Keep it to 1-2 sentences that hook the reader. - - - - - -* Bullet point of what reader will learn -* Another learning outcome -* Keep to 3-5 items - - - -## First Section {/*first-section*/} - -Content with examples... - - - -* Summary bullet of key point -* Another summary point - - - - - -#### Challenge Title {/*challenge-id*/} - -Challenge description... - - -{/* problem code */} - - - - -Explanation and solution... - - -{/* solution code */} - - - - - -``` - -### Reference Page Template (`src/content/reference/`) - -```mdx ---- -title: hookName ---- - - - -`hookName` is a React Hook that lets you [brief description]. - -\`\`\`js -const result = hookName(arg) -\`\`\` - - - - - ---- - -## Reference {/*reference*/} - -### `hookName(arg)` {/*hookname*/} - -Call `hookName` at the top level of your component to... - -\`\`\`js -import { hookName } from 'react'; - -function MyComponent() { - const result = hookName(initialValue); - // ... -\`\`\` - -[See more examples below.](#usage) - -#### Parameters {/*parameters*/} - -* `arg`: Description of the parameter. - -#### Returns {/*returns*/} - -Description of return value. - -#### Caveats {/*caveats*/} - -* Caveat about usage. -* Another important caveat. - ---- - -## Usage {/*usage*/} - -### Common Use Case {/*common-use-case*/} - -Explanation with examples... - ---- - -## Troubleshooting {/*troubleshooting*/} - -### Common Problem {/*common-problem*/} - -How to solve it... -``` - ---- - -## Tone & Voice Guidelines - -### Learn Pages -- Conversational, friendly -- Address the reader as "you" -- "Here's what that looks like..." -- "You might be wondering..." -- "Let's see how this works..." - -### Reference Pages -- Precise, technical -- Still use "you" but more direct -- "Call `useState` at the top level..." -- "This Hook returns..." - -### Universal Rules -- **Capitalize React terms:** Hook, Effect, State, Context, Ref, Component, Transition -- **Capitalize:** Server Component, Client Component, Server Action, Error Boundary, Suspense -- **Use proper product names:** ESLint, TypeScript, JavaScript (not lowercase) -- **Use bold** for key concepts: **state variable**, **event handler** -- **Use italics** for new terms being defined: *event handlers* -- Avoid "simple", "easy", "just" - these can be dismissive -- Prefer concrete examples over abstract explanations -- No time estimates ("quick", "takes X minutes") -- Frame feature differences as "capabilities" not "advantages/disadvantages" -- Avoid passive voice and jargon - -### Avoiding Jargon - -React docs explain technical concepts in plain language. Follow these patterns: - -**Don't use CS jargon without explanation:** -- ❌ "State updates are atomic" -- ✅ "React waits until all state updates are done before re-rendering" - -- ❌ "Components must be idempotent" -- ✅ "Given the same inputs, a component always returns the same output" - -- ❌ "Rendering must be deterministic" -- ✅ "React expects the same inputs to produce the same result" - -**Terms to avoid or always explain:** -- "atomic" → describe what actually happens (all-or-nothing, batched together) -- "idempotent" → "same inputs, same output" -- "deterministic" → "predictable", "same result every time" -- "memoize/memoization" → "remember the result", "skip recalculating" -- "referentially transparent" → avoid entirely, explain the behavior -- "invariant" → "rule that must always be true", "requirement" -- "reify" → avoid entirely, describe what's being created - -**Use analogies the docs already establish:** -- Rendering = preparing food in a kitchen -- Committing = placing the order on the table -- Batching = waiter collecting the full order before going to kitchen -- State = snapshot/photograph at a moment in time -- Pure functions = math formulas (y = 2x always gives same result) - -**Pattern: Explain behavior, then name it** -```markdown -React waits until all code in the event handlers has run before -processing your state updates. This is called *batching*. -``` - -Not: -```markdown -React uses batching to process state updates atomically. -``` - ---- - -## Code Style Rules (Enforced in PR Review) - -These rules are strictly enforced during PR review: - -### Component Definitions -```js -// ✅ Correct - function declaration -function MyInput({ value, onChange, ref }) { - return ; -} -export default MyInput; - -// 🚫 Wrong - arrow function for component -const MyInput = ({ value, onChange, ref }) => { - return ; -}; -``` - -### Event Handlers -```js -// ✅ Correct - use 'e' for event parameter -