diff --git a/package.json b/package.json
index 0efe373e29..c2a84b1ea2 100644
--- a/package.json
+++ b/package.json
@@ -63,7 +63,7 @@
"asyncro": "^3.0.0",
"autoprefixer": "^10.4.2",
"babel-eslint": "10.x",
- "babel-plugin-react-compiler": "^19.1.0-rc.3",
+ "babel-plugin-react-compiler": "^1.0.0",
"chalk": "4.1.2",
"eslint": "7.x",
"eslint-config-next": "12.0.3",
diff --git a/public/images/blog/react-foundation/react_foundation_logo.png b/public/images/blog/react-foundation/react_foundation_logo.png
new file mode 100644
index 0000000000..51c19598f6
Binary files /dev/null and b/public/images/blog/react-foundation/react_foundation_logo.png differ
diff --git a/public/images/blog/react-foundation/react_foundation_logo.webp b/public/images/blog/react-foundation/react_foundation_logo.webp
new file mode 100644
index 0000000000..89efa6027b
Binary files /dev/null and b/public/images/blog/react-foundation/react_foundation_logo.webp differ
diff --git a/public/images/blog/react-foundation/react_foundation_logo_dark.png b/public/images/blog/react-foundation/react_foundation_logo_dark.png
new file mode 100644
index 0000000000..4aedaf4641
Binary files /dev/null and b/public/images/blog/react-foundation/react_foundation_logo_dark.png differ
diff --git a/public/images/blog/react-foundation/react_foundation_logo_dark.webp b/public/images/blog/react-foundation/react_foundation_logo_dark.webp
new file mode 100644
index 0000000000..09b48b70d7
Binary files /dev/null and b/public/images/blog/react-foundation/react_foundation_logo_dark.webp differ
diff --git a/public/images/blog/react-foundation/react_foundation_member_logos.png b/public/images/blog/react-foundation/react_foundation_member_logos.png
new file mode 100644
index 0000000000..e836596937
Binary files /dev/null and b/public/images/blog/react-foundation/react_foundation_member_logos.png differ
diff --git a/public/images/blog/react-foundation/react_foundation_member_logos.webp b/public/images/blog/react-foundation/react_foundation_member_logos.webp
new file mode 100644
index 0000000000..babb3d57c5
Binary files /dev/null and b/public/images/blog/react-foundation/react_foundation_member_logos.webp differ
diff --git a/public/images/blog/react-foundation/react_foundation_member_logos_dark.png b/public/images/blog/react-foundation/react_foundation_member_logos_dark.png
new file mode 100644
index 0000000000..116e40337a
Binary files /dev/null and b/public/images/blog/react-foundation/react_foundation_member_logos_dark.png differ
diff --git a/public/images/blog/react-foundation/react_foundation_member_logos_dark.webp b/public/images/blog/react-foundation/react_foundation_member_logos_dark.webp
new file mode 100644
index 0000000000..5fcf38ca99
Binary files /dev/null and b/public/images/blog/react-foundation/react_foundation_member_logos_dark.webp differ
diff --git a/public/images/docs/diagrams/19_2_batching_after.dark.png b/public/images/docs/diagrams/19_2_batching_after.dark.png
new file mode 100644
index 0000000000..29ff140939
Binary files /dev/null and b/public/images/docs/diagrams/19_2_batching_after.dark.png differ
diff --git a/public/images/docs/diagrams/19_2_batching_after.png b/public/images/docs/diagrams/19_2_batching_after.png
new file mode 100644
index 0000000000..0ae652f792
Binary files /dev/null and b/public/images/docs/diagrams/19_2_batching_after.png differ
diff --git a/public/images/docs/diagrams/19_2_batching_before.dark.png b/public/images/docs/diagrams/19_2_batching_before.dark.png
new file mode 100644
index 0000000000..758afceb15
Binary files /dev/null and b/public/images/docs/diagrams/19_2_batching_before.dark.png differ
diff --git a/public/images/docs/diagrams/19_2_batching_before.png b/public/images/docs/diagrams/19_2_batching_before.png
new file mode 100644
index 0000000000..7e260135f0
Binary files /dev/null and b/public/images/docs/diagrams/19_2_batching_before.png differ
diff --git a/public/images/docs/performance-tracks/changed-props.dark.png b/public/images/docs/performance-tracks/changed-props.dark.png
new file mode 100644
index 0000000000..6709a7ea88
Binary files /dev/null and b/public/images/docs/performance-tracks/changed-props.dark.png differ
diff --git a/public/images/docs/performance-tracks/changed-props.png b/public/images/docs/performance-tracks/changed-props.png
new file mode 100644
index 0000000000..33efe92893
Binary files /dev/null and b/public/images/docs/performance-tracks/changed-props.png differ
diff --git a/public/images/docs/performance-tracks/components-effects.dark.png b/public/images/docs/performance-tracks/components-effects.dark.png
new file mode 100644
index 0000000000..57e3a30b09
Binary files /dev/null and b/public/images/docs/performance-tracks/components-effects.dark.png differ
diff --git a/public/images/docs/performance-tracks/components-effects.png b/public/images/docs/performance-tracks/components-effects.png
new file mode 100644
index 0000000000..ff315b99df
Binary files /dev/null and b/public/images/docs/performance-tracks/components-effects.png differ
diff --git a/public/images/docs/performance-tracks/components-render.dark.png b/public/images/docs/performance-tracks/components-render.dark.png
new file mode 100644
index 0000000000..c0608b153f
Binary files /dev/null and b/public/images/docs/performance-tracks/components-render.dark.png differ
diff --git a/public/images/docs/performance-tracks/components-render.png b/public/images/docs/performance-tracks/components-render.png
new file mode 100644
index 0000000000..4367377670
Binary files /dev/null and b/public/images/docs/performance-tracks/components-render.png differ
diff --git a/public/images/docs/performance-tracks/overview.dark.png b/public/images/docs/performance-tracks/overview.dark.png
new file mode 100644
index 0000000000..07513fe90b
Binary files /dev/null and b/public/images/docs/performance-tracks/overview.dark.png differ
diff --git a/public/images/docs/performance-tracks/overview.png b/public/images/docs/performance-tracks/overview.png
new file mode 100644
index 0000000000..835a247cf6
Binary files /dev/null and b/public/images/docs/performance-tracks/overview.png differ
diff --git a/public/images/docs/performance-tracks/scheduler-cascading-update.dark.png b/public/images/docs/performance-tracks/scheduler-cascading-update.dark.png
new file mode 100644
index 0000000000..beb4512d2d
Binary files /dev/null and b/public/images/docs/performance-tracks/scheduler-cascading-update.dark.png differ
diff --git a/public/images/docs/performance-tracks/scheduler-cascading-update.png b/public/images/docs/performance-tracks/scheduler-cascading-update.png
new file mode 100644
index 0000000000..8631c4896f
Binary files /dev/null and b/public/images/docs/performance-tracks/scheduler-cascading-update.png differ
diff --git a/public/images/docs/performance-tracks/scheduler-update.dark.png b/public/images/docs/performance-tracks/scheduler-update.dark.png
new file mode 100644
index 0000000000..df252663a4
Binary files /dev/null and b/public/images/docs/performance-tracks/scheduler-update.dark.png differ
diff --git a/public/images/docs/performance-tracks/scheduler-update.png b/public/images/docs/performance-tracks/scheduler-update.png
new file mode 100644
index 0000000000..79a361d2aa
Binary files /dev/null and b/public/images/docs/performance-tracks/scheduler-update.png differ
diff --git a/public/images/docs/performance-tracks/scheduler.dark.png b/public/images/docs/performance-tracks/scheduler.dark.png
new file mode 100644
index 0000000000..7e48020f8a
Binary files /dev/null and b/public/images/docs/performance-tracks/scheduler.dark.png differ
diff --git a/public/images/docs/performance-tracks/scheduler.png b/public/images/docs/performance-tracks/scheduler.png
new file mode 100644
index 0000000000..1cd07a1447
Binary files /dev/null and b/public/images/docs/performance-tracks/scheduler.png differ
diff --git a/public/images/docs/performance-tracks/server-overview.dark.png b/public/images/docs/performance-tracks/server-overview.dark.png
new file mode 100644
index 0000000000..221fb1204a
Binary files /dev/null and b/public/images/docs/performance-tracks/server-overview.dark.png differ
diff --git a/public/images/docs/performance-tracks/server-overview.png b/public/images/docs/performance-tracks/server-overview.png
new file mode 100644
index 0000000000..85c7eed27a
Binary files /dev/null and b/public/images/docs/performance-tracks/server-overview.png differ
diff --git a/src/components/MDX/Sandpack/template.ts b/src/components/MDX/Sandpack/template.ts
index 358c8616ed..ed594887bd 100644
--- a/src/components/MDX/Sandpack/template.ts
+++ b/src/components/MDX/Sandpack/template.ts
@@ -35,8 +35,8 @@ root.render(
eject: 'react-scripts eject',
},
dependencies: {
- react: '^19.1.0',
- 'react-dom': '^19.1.0',
+ react: '^19.2.0',
+ 'react-dom': '^19.2.0',
'react-scripts': '^5.0.0',
},
},
diff --git a/src/components/MDX/SandpackWithHTMLOutput.tsx b/src/components/MDX/SandpackWithHTMLOutput.tsx
index c5149deb94..49e980d324 100644
--- a/src/components/MDX/SandpackWithHTMLOutput.tsx
+++ b/src/components/MDX/SandpackWithHTMLOutput.tsx
@@ -56,8 +56,8 @@ export default function formatHTML(markup) {
const packageJSON = `
{
"dependencies": {
- "react": "18.3.0-canary-6db7f4209-20231021",
- "react-dom": "18.3.0-canary-6db7f4209-20231021",
+ "react": "^19.2.0",
+ "react-dom": "^19.2.0",
"react-scripts": "^5.0.0",
"html-format": "^1.1.2"
},
diff --git a/src/content/blog/2024/10/21/react-compiler-beta-release.md b/src/content/blog/2024/10/21/react-compiler-beta-release.md
index 6ef13a3399..3e251d2107 100644
--- a/src/content/blog/2024/10/21/react-compiler-beta-release.md
+++ b/src/content/blog/2024/10/21/react-compiler-beta-release.md
@@ -12,9 +12,15 @@ October 21, 2024 by [Lauren Tan](https://twitter.com/potetotes).
+<<<<<<< HEAD
### React Compiler 现在处于 RC 版本!{/*react-compiler-is-now-in-rc*/}
有关详细信息,请参阅 [RC 博客文章](/blog/2025/04/21/react-compiler-rc)。
+=======
+### React Compiler is now stable! {/*react-compiler-is-now-in-rc*/}
+
+Please see the [stable release blog post](/blog/2025/10/07/react-compiler-1) for details.
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
diff --git a/src/content/blog/2025/04/21/react-compiler-rc.md b/src/content/blog/2025/04/21/react-compiler-rc.md
deleted file mode 100644
index 2ebbf3baeb..0000000000
--- a/src/content/blog/2025/04/21/react-compiler-rc.md
+++ /dev/null
@@ -1,128 +0,0 @@
----
-title: "React Compiler RC"
-author: Lauren Tan and Mofei Zhang
-date: 2025/04/21
-description: We are releasing the compiler's first Release Candidate (RC) today.
-
----
-
-April 21, 2025 by [Lauren Tan](https://x.com/potetotes) and [Mofei Zhang](https://x.com/zmofei).
-
----
-
-
-
-The React team is excited to share new updates:
-
-
-
-1. We're publishing React Compiler RC today, in preparation of the compiler's stable release.
-2. We're merging `eslint-plugin-react-compiler` into `eslint-plugin-react-hooks`.
-3. We've added support for swc and are working with oxc to support Babel-free builds.
-
----
-
-[React Compiler](https://react.dev/learn/react-compiler) is a build-time tool that optimizes your React app through automatic memoization. Last year, we published React Compiler’s [first beta](https://react.dev/blog/2024/10/21/react-compiler-beta-release) and received lots of great feedback and contributions. We’re excited about the wins we’ve seen from folks adopting the compiler (see case studies from [Sanity Studio](https://github.com/reactwg/react-compiler/discussions/33) and [Wakelet](https://github.com/reactwg/react-compiler/discussions/52)) and are working towards a stable release.
-
-We are releasing the compiler's first Release Candidate (RC) today. The RC is intended to be a stable and near-final version of the compiler, and safe to try out in production.
-
-## Use React Compiler RC today {/*use-react-compiler-rc-today*/}
-To install the RC:
-
-npm
-
-{`npm install --save-dev --save-exact babel-plugin-react-compiler@rc`}
-
-
-pnpm
-
-{`pnpm add --save-dev --save-exact babel-plugin-react-compiler@rc`}
-
-
-yarn
-
-{`yarn add --dev --exact babel-plugin-react-compiler@rc`}
-
-
-As part of the RC, we've been making React Compiler easier to add to your projects and added optimizations to how the compiler generates memoization. React Complier now supports optional chains and array indices as dependencies. We're exploring how to infer even more dependencies like equality checks and string interpolation. These improvements ultimately result in fewer re-renders and more responsive UIs.
-
-We have also heard from the community that the ref-in-render validation sometimes has false positives. Since as a general philosophy we want you to be able to fully trust in the compiler's error messages and hints, we are turning it off by default for now. We will keep working to improve this validation, and we will re-enable it in a follow up release.
-
-You can find more details on using the Compiler in [our docs](https://react.dev/learn/react-compiler).
-
-## Feedback {/*feedback*/}
-During the RC period, we encourage all React users to try the compiler and provide feedback in the React repo. Please [open an issue](https://github.com/facebook/react/issues) if you encounter any bugs or unexpected behavior. If you have a general question or suggestion, please post them in the [React Compiler Working Group](https://github.com/reactwg/react-compiler/discussions).
-
-## Backwards Compatibility {/*backwards-compatibility*/}
-As noted in the Beta announcement, React Compiler is compatible with React 17 and up. If you are not yet on React 19, you can use React Compiler by specifying a minimum target in your compiler config, and adding `react-compiler-runtime` as a dependency. You can find docs on this [here](https://react.dev/learn/react-compiler#using-react-compiler-with-react-17-or-18).
-
-## Migrating from eslint-plugin-react-compiler to eslint-plugin-react-hooks {/*migrating-from-eslint-plugin-react-compiler-to-eslint-plugin-react-hooks*/}
-If you have already installed eslint-plugin-react-compiler, you can now remove it and use `eslint-plugin-react-hooks@rc`. Many thanks to [@michaelfaith](https://bsky.app/profile/michael.faith) for contributing to this improvement!
-
-To install:
-
-npm
-
-{`npm install --save-dev eslint-plugin-react-hooks@rc`}
-
-
-pnpm
-
-{`pnpm add --save-dev eslint-plugin-react-hooks@rc`}
-
-
-yarn
-
-{`yarn add --dev eslint-plugin-react-hooks@rc`}
-
-
-```js
-// eslint.config.js
-import * as reactHooks from 'eslint-plugin-react-hooks';
-
-export default [
- // Flat Config (eslint 9+)
- reactHooks.configs.recommended,
-
- // Legacy Config
- reactHooks.configs['recommended-latest']
-];
-```
-
-To enable the React Compiler rule, add `'react-hooks/react-compiler': 'error'` to your ESLint configuration.
-
-The linter does not require the compiler to be installed, so there's no risk in upgrading eslint-plugin-react-hooks. We recommend everyone upgrade today.
-
-## swc support (experimental) {/*swc-support-experimental*/}
-React Compiler can be installed across [several build tools](/learn/react-compiler#installation) such as Babel, Vite, and Rsbuild.
-
-In addition to those tools, we have been collaborating with Kang Dongyoon ([@kdy1dev](https://x.com/kdy1dev)) from the [swc](https://swc.rs/) team on adding additional support for React Compiler as an swc plugin. While this work isn't done, Next.js build performance should now be considerably faster when the [React Compiler is enabled in your Next.js app](https://nextjs.org/docs/app/api-reference/config/next-config-js/reactCompiler).
-
-We recommend using Next.js [15.3.1](https://github.com/vercel/next.js/releases/tag/v15.3.1) or greater to get the best build performance.
-
-Vite users can continue to use [vite-plugin-react](https://github.com/vitejs/vite-plugin-react) to enable the compiler, by adding it as a [Babel plugin](https://react.dev/learn/react-compiler#usage-with-vite). We are also working with the [oxc](https://oxc.rs/) team to [add support for the compiler](https://github.com/oxc-project/oxc/issues/10048). Once [rolldown](https://github.com/rolldown/rolldown) is officially released and supported in Vite and oxc support is added for React Compiler, we'll update the docs with information on how to migrate.
-
-## Upgrading React Compiler {/*upgrading-react-compiler*/}
-React Compiler works best when the auto-memoization applied is strictly for performance. Future versions of the compiler may change how memoization is applied, for example it could become more granular and precise.
-
-However, because product code may sometimes break the [rules of React](https://react.dev/reference/rules) in ways that aren't always statically detectable in JavaScript, changing memoization can occasionally have unexpected results. For example, a previously memoized value might be used as a dependency for a useEffect somewhere in the component tree. Changing how or whether this value is memoized can cause over or under-firing of that useEffect. While we encourage [useEffect only for synchronization](https://react.dev/learn/synchronizing-with-effects), your codebase may have useEffects that cover other use-cases such as effects that needs to only run in response to specific values changing.
-
-In other words, changing memoization may under rare circumstances cause unexpected behavior. For this reason, we recommend following the Rules of React and employing continuous end-to-end testing of your app so you can upgrade the compiler with confidence and identify any rules of React violations that might cause issues.
-
-If you don't have good test coverage, we recommend pinning the compiler to an exact version (eg `19.1.0`) rather than a SemVer range (eg `^19.1.0`). You can do this by passing the `--save-exact` (npm/pnpm) or `--exact` flags (yarn) when upgrading the compiler. You should then do any upgrades of the compiler manually, taking care to check that your app still works as expected.
-
-## Roadmap to Stable {/*roadmap-to-stable*/}
-*This is not a final roadmap, and is subject to change.*
-
-After a period of final feedback from the community on the RC, we plan on a Stable Release for the compiler.
-
-* ✅ Experimental: Released at React Conf 2024, primarily for feedback from application developers.
-* ✅ Public Beta: Available today, for feedback from library authors.
-* ✅ Release Candidate (RC): React Compiler works for the majority of rule-following apps and libraries without issue.
-* General Availability: After final feedback period from the community.
-
-Post-Stable, we plan to add more compiler optimizations and improvements. This includes both continual improvements to automatic memoization, and new optimizations altogether, with minimal to no change of product code. Each upgrade will continue to improve performance and add better handling of diverse JavaScript and React patterns.
-
----
-
-Thanks to [Joe Savona](https://x.com/en_JS), [Jason Bonta](https://x.com/someextent), [Jimmy Lai](https://x.com/feedthejim), and [Kang Dongyoon](https://x.com/kdy1dev) (@kdy1dev) for reviewing and editing this post.
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 c4447188a1..21bca07aca 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
@@ -18,11 +18,17 @@ description: 在 React Labs 系列文章中,我们会介绍正在积极研究
+<<<<<<< HEAD
React Conf 2025 将于 10 月 7-8 日在内华达州亨德森举行!
我们正在寻找演讲者,帮助我们创建关于本文所涵盖功能的演讲。如果你有兴趣在 ReactConf 上发言,[请在此申请](https://forms.reform.app/react-conf/call-for-speakers/)(无需提交演讲提案)。
有关门票、免费直播、赞助等更多信息,请查看 [React Conf 网站](https://conf.react.dev)。
+=======
+React Conf 2025 is scheduled for October 7–8 in Henderson, Nevada!
+
+Watch the livestream on [the React Conf website](https://conf.react.dev).
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
@@ -68,7 +74,11 @@ React 视图过渡是一个新的实验性功能,它让你能更轻松地为
```
+<<<<<<< HEAD
这个新组件让你可以声明式地定义"要"在动画激活时进行动画处理的内容。
+=======
+This new component lets you declaratively define "what" to animate when an animation is activated.
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
你可以通过使用以下三种触发器之一来定义"何时"进行动画:
@@ -101,9 +111,15 @@ const deferred = useDeferredValue(value);
当 DOM 因动画触发器(如 `startTransition`、`useDeferredValue` 或 `Suspense` 后备方案切换到内容)而更新时,React 将使用[声明式启发法](/reference/react/ViewTransition#viewtransition)自动确定要为动画激活哪些 `` 组件。然后浏览器将运行在 CSS 中定义的动画。
+<<<<<<< HEAD
如果你熟悉浏览器的视图过渡 API 并想了解 React 如何支持它,请查看文档中的[`` 如何工作](/reference/react/ViewTransition#how-does-viewtransition-work)。
在本文中,让我们看几个使用视图过渡的例子。
+=======
+If you're familiar with the browser's View Transition API and want to know how React supports it, check out [How does `` Work](/reference/react/ViewTransition#how-does-viewtransition-work) in the docs.
+
+In this post, let's take a look at a few examples of how to use View Transitions.
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
我们将从这个应用开始,它不会为以下任何交互添加动画:
- 点击视频查看详情。
@@ -1247,8 +1263,8 @@ root.render(
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest"
},
"scripts": {
@@ -1296,18 +1312,28 @@ function navigate(url) {
当 `url` 改变时,`` 和新路由会被渲染。由于 `` 是在 `startTransition` 内部更新的,因此 `` 会被激活以进行动画处理。
+<<<<<<< HEAD
默认情况下,视图过渡包含浏览器默认的交叉淡入淡出动画。将其添加到我们的示例中,现在每当我们在页面之间导航时都会有交叉淡入淡出效果:
+=======
+By default, View Transitions include the browser default cross-fade animation. Adding this to our example, we now have a cross-fade whenever we navigate between pages:
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
```js src/App.js active
-import {unstable_ViewTransition as ViewTransition} from 'react'; import Details from './Details'; import Home from './Home'; import {useRouter} from './router';
+import {ViewTransition} from 'react'; import Details from './Details';
+import Home from './Home'; import {useRouter} from './router';
export default function App() {
const {url} = useRouter();
+<<<<<<< HEAD
// 使用 ViewTransition 在页面间进行动画。
// 默认情况下不需要添加 CSS。
+=======
+ // Use ViewTransition to animate between pages.
+ // No additional CSS needed by default.
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
return (
{url === '/' ? : }
@@ -1564,7 +1590,7 @@ export function IconSearch(props) {
```
```js src/Layout.js
-import {unstable_ViewTransition as ViewTransition} from 'react'; import { useIsNavPending } from "./router";
+import {ViewTransition} from 'react'; import { useIsNavPending } from "./router";
export default function Page({ heading, children }) {
const isPending = useIsNavPending();
@@ -2443,8 +2469,8 @@ root.render(
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest"
},
"scripts": {
@@ -2458,7 +2484,11 @@ root.render(
+<<<<<<< HEAD
由于我们的路由器已经使用 `startTransition` 更新路由,添加 `` 的这一行更改就会激活默认的交叉淡入淡出动画。
+=======
+Since our router already updates the route using `startTransition`, this one line change to add `` activates with the default cross-fade animation.
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
如果你好奇这是如何工作的,请查看文档中的 [`` 如何工作?](/reference/react/ViewTransition#how-does-viewtransition-work)
@@ -2466,7 +2496,11 @@ root.render(
#### 退出 `` 动画 {/*opting-out-of-viewtransition-animations*/}
+<<<<<<< HEAD
在这个例子中,为了简单起见,我们将应用的根部分包装在 `` 中,但这意味着应用中的所有过渡都将有动画效果,这可能会导致意外的动画。
+=======
+In this example, we're wrapping the root of the app in `` for simplicity, but this means that all transitions in the app will be animated, which can lead to unexpected animations.
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
为了解决这个问题,我们用 `"none"` 包装路由子组件,这样每个页面都可以控制自己的动画:
@@ -2477,7 +2511,11 @@ root.render(
```
+<<<<<<< HEAD
在实践中,导航应该通过 "enter" 和 "exit" 属性或使用 Transition Types 来完成。
+=======
+In practice, navigations should be done via "enter" and "exit" props, or by using Transition Types.
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
@@ -2512,7 +2550,7 @@ root.render(
```js src/App.js active
-import { unstable_ViewTransition as ViewTransition } from "react";
+import { ViewTransition } from "react";
import Details from "./Details";
import Home from "./Home";
import { useRouter } from "./router";
@@ -2778,7 +2816,7 @@ export function IconSearch(props) {
```
```js src/Layout.js hidden
-import {unstable_ViewTransition as ViewTransition} from 'react'; import { useIsNavPending } from "./router";
+import {ViewTransition} from 'react'; import { useIsNavPending } from "./router";
export default function Page({ heading, children }) {
const isPending = useIsNavPending();
@@ -3671,8 +3709,8 @@ root.render(
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest"
},
"scripts": {
@@ -3705,7 +3743,7 @@ root.render(
```js src/App.js
-import { unstable_ViewTransition as ViewTransition } from "react";
+import { ViewTransition } from "react";
import Details from "./Details";
import Home from "./Home";
import { useRouter } from "./router";
@@ -3972,7 +4010,7 @@ export function IconSearch(props) {
```
```js src/Layout.js hidden
-import {unstable_ViewTransition as ViewTransition} from 'react'; import { useIsNavPending } from "./router";
+import {ViewTransition} from 'react'; import { useIsNavPending } from "./router";
export default function Page({ heading, children }) {
const isPending = useIsNavPending();
@@ -4029,7 +4067,7 @@ export default function LikeButton({video}) {
```
```js src/Videos.js active
-import { useState, unstable_ViewTransition as ViewTransition } from "react"; import LikeButton from "./LikeButton"; import { useRouter } from "./router"; import { PauseIcon, PlayIcon } from "./Icons"; import { startTransition } from "react";
+import { useState, ViewTransition } from "react"; import LikeButton from "./LikeButton"; import { useRouter } from "./router"; import { PauseIcon, PlayIcon } from "./Icons"; import { startTransition } from "react";
export function Thumbnail({ video, children }) {
// Add a name to animate with a shared element transition.
@@ -4880,8 +4918,8 @@ root.render(
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest"
},
"scripts": {
@@ -4962,7 +5000,7 @@ Now we can animate the header along with thumbnail based on navigation type:
```js src/App.js hidden
-import { unstable_ViewTransition as ViewTransition } from "react";
+import { ViewTransition } from "react";
import Details from "./Details";
import Home from "./Home";
import { useRouter } from "./router";
@@ -5227,7 +5265,7 @@ export function IconSearch(props) {
```
```js src/Layout.js active
-import {unstable_ViewTransition as ViewTransition} from 'react'; import { useIsNavPending } from "./router";
+import {ViewTransition} from 'react'; import { useIsNavPending } from "./router";
export default function Page({ heading, children }) {
const isPending = useIsNavPending();
@@ -5291,7 +5329,7 @@ export default function LikeButton({video}) {
```
```js src/Videos.js hidden
-import { useState, unstable_ViewTransition as ViewTransition } from "react";
+import { useState, ViewTransition } from "react";
import LikeButton from "./LikeButton";
import { useRouter } from "./router";
import { PauseIcon, PlayIcon } from "./Icons";
@@ -5442,7 +5480,7 @@ export function fetchVideoDetails(id) {
```
```js src/router.js
-import {useState, createContext, use, useTransition, useLayoutEffect, useEffect, unstable_addTransitionType as addTransitionType} from "react";
+import {useState, createContext, use, useTransition, useLayoutEffect, useEffect, addTransitionType} from "react";
export function Router({ children }) {
const [isPending, startTransition] = useTransition();
@@ -6196,8 +6234,8 @@ root.render(
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest"
},
"scripts": {
@@ -6213,7 +6251,11 @@ root.render(
### 为 Suspense 边界添加动画 {/*animating-suspense-boundaries*/}
+<<<<<<< HEAD
Suspense 也会激活视图过渡。
+=======
+Suspense will also activate View Transitions.
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
要为后备方案到内容的过渡添加动画,我们可以用 `` 包装 `Suspense`:
@@ -6230,7 +6272,7 @@ Suspense 也会激活视图过渡。
```js src/App.js hidden
-import { unstable_ViewTransition as ViewTransition } from "react";
+import { ViewTransition } from "react";
import Details from "./Details";
import Home from "./Home";
import { useRouter } from "./router";
@@ -6248,7 +6290,7 @@ export default function App() {
```
```js src/Details.js active
-import { use, Suspense, unstable_ViewTransition as ViewTransition } from "react"; import { fetchVideo, fetchVideoDetails } from "./data"; import { Thumbnail, VideoControls } from "./Videos"; import { useRouter } from "./router"; import Layout from "./Layout"; import { ChevronLeft } from "./Icons";
+import { use, Suspense, ViewTransition } from "react"; import { fetchVideo, fetchVideoDetails } from "./data"; import { Thumbnail, VideoControls } from "./Videos"; import { useRouter } from "./router"; import Layout from "./Layout"; import { ChevronLeft } from "./Icons";
function VideoDetails({ id }) {
// Cross-fade the fallback to content.
@@ -6498,7 +6540,7 @@ export function IconSearch(props) {
```
```js src/Layout.js hidden
-import {unstable_ViewTransition as ViewTransition} from 'react';
+import {ViewTransition} from 'react';
import { useIsNavPending } from "./router";
export default function Page({ heading, children }) {
@@ -6563,7 +6605,7 @@ export default function LikeButton({video}) {
```
```js src/Videos.js hidden
-import { useState, unstable_ViewTransition as ViewTransition } from "react";
+import { useState, ViewTransition } from "react";
import LikeButton from "./LikeButton";
import { useRouter } from "./router";
import { PauseIcon, PlayIcon } from "./Icons";
@@ -6714,7 +6756,7 @@ export function fetchVideoDetails(id) {
```
```js src/router.js hidden
-import {useState, createContext, use, useTransition, useLayoutEffect, useEffect, unstable_addTransitionType as addTransitionType} from "react";
+import {useState, createContext, use, useTransition, useLayoutEffect, useEffect, addTransitionType} from "react";
export function Router({ children }) {
const [isPending, startTransition] = useTransition();
@@ -7494,8 +7536,8 @@ root.render(
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest"
},
"scripts": {
@@ -7544,7 +7586,7 @@ Now, the Suspense content replaces the fallback with a sliding animation:
```js src/App.js hidden
-import { unstable_ViewTransition as ViewTransition } from "react";
+import { ViewTransition } from "react";
import Details from "./Details";
import Home from "./Home";
import { useRouter } from "./router";
@@ -7562,7 +7604,7 @@ export default function App() {
```
```js src/Details.js active
-import { use, Suspense, unstable_ViewTransition as ViewTransition } from "react"; import { fetchVideo, fetchVideoDetails } from "./data"; import { Thumbnail, VideoControls } from "./Videos"; import { useRouter } from "./router"; import Layout from "./Layout"; import { ChevronLeft } from "./Icons";
+import { use, Suspense, ViewTransition } from "react"; import { fetchVideo, fetchVideoDetails } from "./data"; import { Thumbnail, VideoControls } from "./Videos"; import { useRouter } from "./router"; import Layout from "./Layout"; import { ChevronLeft } from "./Icons";
function VideoDetails({ id }) {
return (
@@ -7819,7 +7861,7 @@ export function IconSearch(props) {
```
```js src/Layout.js hidden
-import {unstable_ViewTransition as ViewTransition} from 'react';
+import {ViewTransition} from 'react';
import { useIsNavPending } from "./router";
export default function Page({ heading, children }) {
@@ -7884,7 +7926,7 @@ export default function LikeButton({video}) {
```
```js src/Videos.js hidden
-import { useState, unstable_ViewTransition as ViewTransition } from "react";
+import { useState, ViewTransition } from "react";
import LikeButton from "./LikeButton";
import { useRouter } from "./router";
import { PauseIcon, PlayIcon } from "./Icons";
@@ -8035,7 +8077,7 @@ export function fetchVideoDetails(id) {
```
```js src/router.js hidden
-import {useState, createContext, use, useTransition, useLayoutEffect, useEffect, unstable_addTransitionType as addTransitionType} from "react";
+import {useState, createContext, use, useTransition, useLayoutEffect, useEffect, addTransitionType} from "react";
export function Router({ children }) {
const [isPending, startTransition] = useTransition();
@@ -8815,8 +8857,8 @@ root.render(
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest"
},
"scripts": {
@@ -8858,7 +8900,7 @@ Now the items animate as you type in the search bar:
```js src/App.js hidden
-import { unstable_ViewTransition as ViewTransition } from "react";
+import { ViewTransition } from "react";
import Details from "./Details";
import Home from "./Home";
import { useRouter } from "./router";
@@ -8876,7 +8918,7 @@ export default function App() {
```
```js src/Details.js hidden
-import { use, Suspense, unstable_ViewTransition as ViewTransition } from "react";
+import { use, Suspense, ViewTransition } from "react";
import { fetchVideo, fetchVideoDetails } from "./data";
import { Thumbnail, VideoControls } from "./Videos";
import { useRouter } from "./router";
@@ -8951,17 +8993,25 @@ function VideoInfo({ id }) {
```
```js src/Home.js
-import { useId, useState, use, useDeferredValue, unstable_ViewTransition as ViewTransition } from "react";import { Video } from "./Videos";import Layout from "./Layout";import { fetchVideos } from "./data";import { IconSearch } from "./Icons";
+import { useId, useState, use, useDeferredValue, ViewTransition } from "react";import { Video } from "./Videos";import Layout from "./Layout";import { fetchVideos } from "./data";import { IconSearch } from "./Icons";
function SearchList({searchText, videos}) {
+<<<<<<< HEAD
// 通过 useDeferredValue来激活(何时)
+=======
+ // Activate with useDeferredValue ("when")
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
const deferredSearchText = useDeferredValue(searchText);
const filteredVideos = filterVideos(videos, deferredSearchText);
return (
{filteredVideos.map((video) => (
+<<<<<<< HEAD
// 对列表中的每一个子项目进行动画(何地)
+=======
+ // Animate each item in list ("what")
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
@@ -9146,7 +9196,7 @@ export function IconSearch(props) {
```
```js src/Layout.js hidden
-import {unstable_ViewTransition as ViewTransition} from 'react';
+import {ViewTransition} from 'react';
import { useIsNavPending } from "./router";
export default function Page({ heading, children }) {
@@ -9211,7 +9261,7 @@ export default function LikeButton({video}) {
```
```js src/Videos.js hidden
-import { useState, unstable_ViewTransition as ViewTransition } from "react";
+import { useState, ViewTransition } from "react";
import LikeButton from "./LikeButton";
import { useRouter } from "./router";
import { PauseIcon, PlayIcon } from "./Icons";
@@ -9362,7 +9412,7 @@ export function fetchVideoDetails(id) {
```
```js src/router.js hidden
-import {useState, createContext, use, useTransition, useLayoutEffect, useEffect, unstable_addTransitionType as addTransitionType} from "react";
+import {useState, createContext, use, useTransition, useLayoutEffect, useEffect, addTransitionType} from "react";
export function Router({ children }) {
const [isPending, startTransition] = useTransition();
@@ -10156,8 +10206,8 @@ root.render(
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest"
},
"scripts": {
@@ -10182,7 +10232,7 @@ Let's remove the slow fade, and take a look at the final result:
```js src/App.js
-import {unstable_ViewTransition as ViewTransition} from 'react'; import Details from './Details'; import Home from './Home'; import {useRouter} from './router';
+import {ViewTransition} from 'react'; import Details from './Details'; import Home from './Home'; import {useRouter} from './router';
export default function App() {
const {url} = useRouter();
@@ -10197,7 +10247,7 @@ export default function App() {
```
```js src/Details.js
-import { use, Suspense, unstable_ViewTransition as ViewTransition } from "react"; import { fetchVideo, fetchVideoDetails } from "./data"; import { Thumbnail, VideoControls } from "./Videos"; import { useRouter } from "./router"; import Layout from "./Layout"; import { ChevronLeft } from "./Icons";
+import { use, Suspense, ViewTransition } from "react"; import { fetchVideo, fetchVideoDetails } from "./data"; import { Thumbnail, VideoControls } from "./Videos"; import { useRouter } from "./router"; import Layout from "./Layout"; import { ChevronLeft } from "./Icons";
function VideoDetails({id}) {
// Animate from Suspense fallback to content
@@ -10267,17 +10317,25 @@ function VideoInfo({ id }) {
```
```js src/Home.js
-import { useId, useState, use, useDeferredValue, unstable_ViewTransition as ViewTransition } from "react";import { Video } from "./Videos";import Layout from "./Layout";import { fetchVideos } from "./data";import { IconSearch } from "./Icons";
+import { useId, useState, use, useDeferredValue, ViewTransition } from "react";import { Video } from "./Videos";import Layout from "./Layout";import { fetchVideos } from "./data";import { IconSearch } from "./Icons";
function SearchList({searchText, videos}) {
+<<<<<<< HEAD
// 通过 useDeferredValue来激活(何时)
+=======
+ // Activate with useDeferredValue ("when")
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
const deferredSearchText = useDeferredValue(searchText);
const filteredVideos = filterVideos(videos, deferredSearchText);
return (
{filteredVideos.map((video) => (
+<<<<<<< HEAD
// 对列表中的每一个子项目进行动画(何地)
+=======
+ // Animate each item in list ("what")
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
@@ -10462,7 +10520,7 @@ export function IconSearch(props) {
```
```js src/Layout.js
-import {unstable_ViewTransition as ViewTransition} from 'react'; import { useIsNavPending } from "./router";
+import {ViewTransition} from 'react'; import { useIsNavPending } from "./router";
export default function Page({ heading, children }) {
const isPending = useIsNavPending();
@@ -10526,7 +10584,7 @@ export default function LikeButton({video}) {
```
```js src/Videos.js
-import { useState, unstable_ViewTransition as ViewTransition } from "react"; import LikeButton from "./LikeButton"; import { useRouter } from "./router"; import { PauseIcon, PlayIcon } from "./Icons"; import { startTransition } from "react";
+import { useState, ViewTransition } from "react"; import LikeButton from "./LikeButton"; import { useRouter } from "./router"; import { PauseIcon, PlayIcon } from "./Icons"; import { startTransition } from "react";
export function Thumbnail({ video, children }) {
// Add a name to animate with a shared element transition.
@@ -10674,7 +10732,7 @@ export function fetchVideoDetails(id) {
```
```js src/router.js
-import {useState, createContext, use, useTransition, useLayoutEffect, useEffect, unstable_addTransitionType as addTransitionType} from "react";
+import {useState, createContext, use, useTransition, useLayoutEffect, useEffect, addTransitionType} from "react";
export function Router({ children }) {
const [isPending, startTransition] = useTransition();
@@ -11442,8 +11500,8 @@ root.render(
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest"
},
"scripts": {
@@ -11544,7 +11602,7 @@ function App() {
```js src/App.js
-import { unstable_ViewTransition as ViewTransition, unstable_Activity as Activity } from "react"; import Details from "./Details"; import Home from "./Home"; import { useRouter } from "./router";
+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;
export default function App() {
const { url } = useRouter();
@@ -11563,7 +11621,7 @@ export default function App() {
```
```js src/Details.js hidden
-import { use, Suspense, unstable_ViewTransition as ViewTransition } from "react";
+import { use, Suspense, ViewTransition } from "react";
import { fetchVideo, fetchVideoDetails } from "./data";
import { Thumbnail, VideoControls } from "./Videos";
import { useRouter } from "./router";
@@ -11638,10 +11696,14 @@ function VideoInfo({ id }) {
```
```js src/Home.js hidden
-import { useId, useState, use, useDeferredValue, unstable_ViewTransition as ViewTransition } from "react";import { Video } from "./Videos";import Layout from "./Layout";import { fetchVideos } from "./data";import { IconSearch } from "./Icons";
+import { useId, useState, use, useDeferredValue, ViewTransition } from "react";import { Video } from "./Videos";import Layout from "./Layout";import { fetchVideos } from "./data";import { IconSearch } from "./Icons";
function SearchList({searchText, videos}) {
+<<<<<<< HEAD
// 通过 useDeferredValue来激活(何时)
+=======
+ // Activate with useDeferredValue ("when")
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
const deferredSearchText = useDeferredValue(searchText);
const filteredVideos = filterVideos(videos, deferredSearchText);
return (
@@ -11651,7 +11713,11 @@ function SearchList({searchText, videos}) {
)}
{filteredVideos.map((video) => (
+<<<<<<< HEAD
// 对列表中的每一个子项目进行动画(何地)
+=======
+ // Animate each item in list ("what")
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
@@ -11833,7 +11899,7 @@ export function IconSearch(props) {
```
```js src/Layout.js hidden
-import {unstable_ViewTransition as ViewTransition} from 'react'; import { useIsNavPending } from "./router";
+import {ViewTransition} from 'react'; import { useIsNavPending } from "./router";
export default function Page({ heading, children }) {
const isPending = useIsNavPending();
@@ -11897,7 +11963,7 @@ export default function LikeButton({video}) {
```
```js src/Videos.js hidden
-import { useState, unstable_ViewTransition as ViewTransition } from "react";
+import { useState, ViewTransition } from "react";
import LikeButton from "./LikeButton";
import { useRouter } from "./router";
import { PauseIcon, PlayIcon } from "./Icons";
@@ -12048,7 +12114,7 @@ export function fetchVideoDetails(id) {
```
```js src/router.js hidden
-import {useState, createContext, use, useTransition, useLayoutEffect, useEffect, unstable_addTransitionType as addTransitionType} from "react";
+import {useState, createContext, use, useTransition, useLayoutEffect, useEffect, addTransitionType} from "react";
export function Router({ children }) {
const [isPending, startTransition] = useTransition();
@@ -12841,8 +12907,8 @@ root.render(
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest"
},
"scripts": {
@@ -12881,7 +12947,7 @@ With this update, if the content on the next page has time to pre-render, it wil
```js src/App.js
-import { unstable_ViewTransition as ViewTransition, unstable_Activity as Activity, use } from "react"; import Details from "./Details"; import Home from "./Home"; import { useRouter } from "./router"; import {fetchVideos} from './data'
+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;
export default function App() {
const { url } = useRouter();
@@ -12905,7 +12971,7 @@ export default function App() {
```
```js src/Details.js
-import { use, Suspense, unstable_ViewTransition as ViewTransition } from "react"; import { fetchVideo, fetchVideoDetails } from "./data"; import { Thumbnail, VideoControls } from "./Videos"; import { useRouter } from "./router"; import Layout from "./Layout"; import { ChevronLeft } from "./Icons";
+import { use, Suspense, ViewTransition } from "react"; import { fetchVideo, fetchVideoDetails } from "./data"; import { Thumbnail, VideoControls } from "./Videos"; import { useRouter } from "./router"; import Layout from "./Layout"; import { ChevronLeft } from "./Icons";
function VideoDetails({id}) {
// Animate from Suspense fallback to content.
@@ -12976,10 +13042,14 @@ function VideoInfo({ id }) {
```
```js src/Home.js hidden
-import { useId, useState, use, useDeferredValue, unstable_ViewTransition as ViewTransition } from "react";import { Video } from "./Videos";import Layout from "./Layout";import { fetchVideos } from "./data";import { IconSearch } from "./Icons";
+import { useId, useState, use, useDeferredValue, ViewTransition } from "react";import { Video } from "./Videos";import Layout from "./Layout";import { fetchVideos } from "./data";import { IconSearch } from "./Icons";
function SearchList({searchText, videos}) {
+<<<<<<< HEAD
// 通过 useDeferredValue来激活(何时)
+=======
+ // Activate with useDeferredValue ("when")
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
const deferredSearchText = useDeferredValue(searchText);
const filteredVideos = filterVideos(videos, deferredSearchText);
return (
@@ -12989,7 +13059,11 @@ function SearchList({searchText, videos}) {
)}
{filteredVideos.map((video) => (
+<<<<<<< HEAD
// 对列表中的每一个子项目进行动画(何地)
+=======
+ // Animate each item in list ("what")
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
@@ -13171,7 +13245,7 @@ export function IconSearch(props) {
```
```js src/Layout.js hidden
-import {unstable_ViewTransition as ViewTransition} from 'react'; import { useIsNavPending } from "./router";
+import {ViewTransition} from 'react'; import { useIsNavPending } from "./router";
export default function Page({ heading, children }) {
const isPending = useIsNavPending();
@@ -13235,7 +13309,7 @@ export default function LikeButton({video}) {
```
```js src/Videos.js hidden
-import { useState, unstable_ViewTransition as ViewTransition } from "react";
+import { useState, ViewTransition } from "react";
import LikeButton from "./LikeButton";
import { useRouter } from "./router";
import { PauseIcon, PlayIcon } from "./Icons";
@@ -13386,7 +13460,7 @@ export function fetchVideoDetails(id) {
```
```js src/router.js hidden
-import {useState, createContext, use, useTransition, useLayoutEffect, useEffect, unstable_addTransitionType as addTransitionType} from "react";
+import {useState, createContext, use, useTransition, useLayoutEffect, useEffect, addTransitionType} from "react";
export function Router({ children }) {
const [isPending, startTransition] = useTransition();
@@ -14179,8 +14253,8 @@ root.render(
```json package.json hidden
{
"dependencies": {
- "react": "experimental",
- "react-dom": "experimental",
+ "react": "canary",
+ "react-dom": "canary",
"react-scripts": "latest"
},
"scripts": {
@@ -14220,6 +14294,7 @@ root.render(
# 正在开发的功能 {/*features-in-development*/}
+<<<<<<< HEAD
我们还在开发功能来帮助解决以下常见问题。
在我们迭代可能的解决方案时,你可能会看到我们正在测试的一些潜在 API,这些 API 基于我们正在合并的 PR 进行分享。请记住,当我们尝试不同的想法时,我们通常会在尝试后更改或删除不同的解决方案。
@@ -14227,6 +14302,15 @@ root.render(
如果我们过早分享正在开发的解决方案,可能会在社区中造成混乱和困惑。为了平衡透明度和减少困惑,我们只分享了当前正在为其开发解决方案的问题,而不分享我们心中的特定解决方案。
随着这些功能的进展,我们将在博客上宣布它们,并附上文档,以便你可以尝试它们。
+=======
+We're also developing features to help solve the common problems below.
+
+As we iterate on possible solutions, you may see some potential APIs we're testing being shared based on the PRs we are landing. Please keep in mind that as we try different ideas, we often change or remove different solutions after trying them out.
+
+When the solutions we're working on are shared too early, it can create churn and confusion in the community. To balance being transparent and limiting confusion, we're sharing the problems we're currently developing solutions for, without sharing a particular solution we have in mind.
+
+As these features progress, we'll announce them on the blog with docs included so you can try them out.
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
## React 性能追踪 {/*react-performance-tracks*/}
@@ -14259,7 +14343,11 @@ root.render(
- **以函数而非生命周期的方式思考**:hooks 让你可以根据相关的部分(如设置订阅或获取数据)将一个组件拆分成更小的函数,而不是强制基于生命周期方法进行拆分。
- **支持提前编译**:hooks 的设计支持提前编译,减少了由生命周期方法和类的限制导致的无意去优化的陷阱。
+<<<<<<< HEAD
自发布以来,hooks 在 **在组件之间共享代码** 方面取得了成功。Hooks 现在是在组件之间共享逻辑的首选方式,render props 和高阶组件的使用场景减少了。Hooks 还成功支持了像 Fast Refresh 这样的功能,这在类组件中是不可能实现的。
+=======
+Since their release, hooks have been successful at *sharing code between components*. Hooks are now the favored way to share logic between components, and there are less use cases for render props and higher order components. Hooks have also been successful at supporting features like Fast Refresh that were not possible with class components.
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
### Effects 可能很难理解 {/*effects-can-be-hard*/}
@@ -14300,18 +14388,30 @@ useEffect(() => {
return () => {
connection.disconnect();
};
+<<<<<<< HEAD
}); // 编译器插入的依赖项。
+=======
+}); // compiler inserted dependencies.
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
```
使用这段代码,React 编译器可以为你推断依赖项并自动插入它们,这样你就不需要看到或编写它们。通过像[IDE 扩展](#compiler-ide-extension)和[`useEffectEvent`](/reference/react/useEffectEvent)这样的功能,我们可以提供一个 CodeLens 来显示编译器在你需要调试时插入的内容,或通过移除依赖项来优化。这有助于强化编写 Effects 的正确心智模型,即 Effects 可以在任何时候运行,以将你的组件或 hook 的状态与其他内容同步。
+<<<<<<< HEAD
我们希望自动插入依赖项不仅更容易编写,而且通过迫使你从 Effect 的作用角度思考,而不是从组件生命周期角度思考,使它们更容易理解。
+=======
+Our hope is that automatically inserting dependencies is not only easier to write, but that it also makes them easier to understand by forcing you to think in terms of what the Effect does, and not in component lifecycles.
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
---
## 编译器 IDE 扩展 {/*compiler-ide-extension*/}
+<<<<<<< HEAD
本周早些时候[我们分享了](/blog/2025/04/21/react-compiler-rc) React 编译器的候选发布版本,我们正在努力在未来几个月内发布编译器的第一个语义化版本稳定版。
+=======
+Later in 2025 [we shared](/blog/2025/10/07/react-compiler-1) the first stable release of React Compiler, and we're continuing to invest in shipping more improvements.
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
我们还开始探索使用 React 编译器提供信息的方法,以改进对代码的理解和调试。我们开始探索的一个想法是一个由 React 编译器驱动的基于 LSP 的新实验性 React IDE 扩展,类似于 [Lauren Tan 在 React Conf 演讲](https://conf2024.react.dev/talks/5)中使用的扩展。
@@ -14333,7 +14433,11 @@ Fragment refs 仍在研究中。当我们接近完成最终 API 时,我们将
## 手势动画 {/*gesture-animations*/}
+<<<<<<< HEAD
我们还在研究增强视图过渡以支持手势动画的方法,例如滑动打开菜单或滚动浏览照片轮播。
+=======
+We're also researching ways to enhance View Transitions to support gesture animations such as swiping to open a menu, or scroll through a photo carousel.
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
手势因以下几个原因带来新的挑战:
@@ -14357,9 +14461,15 @@ Fragment refs 仍在研究中。当我们接近完成最终 API 时,我们将
const value = use(store);
```
+<<<<<<< HEAD
我们的目标是允许在渲染期间读取外部状态而不会撕裂,并与 React 提供的所有并发功能无缝协作。
这项研究仍处于早期阶段。当我们进一步推进时,我们将分享更多信息,以及新 API 的样子。
+=======
+Our goal is to allow external state to be read during render without tearing, and to work seamlessly with all of the concurrent features React offers.
+
+This research is still early. We'll share more, and what the new APIs will look like, when we're further along.
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
---
diff --git a/src/content/blog/2025/10/01/react-19-2.md b/src/content/blog/2025/10/01/react-19-2.md
new file mode 100644
index 0000000000..51c30f70a2
--- /dev/null
+++ b/src/content/blog/2025/10/01/react-19-2.md
@@ -0,0 +1,339 @@
+---
+title: "React 19.2"
+author: The React Team
+date: 2025/10/01
+description: React 19.2 adds new features like Activity, React Performance Tracks, useEffectEvent, and more.
+---
+
+October 1, 2025 by [The React Team](/community/team)
+
+---
+
+
+
+React 19.2 is now available on npm!
+
+
+
+This is our third release in the last year, following React 19 in December and React 19.1 in June. In this post, we'll give an overview of the new features in React 19.2, and highlight some notable changes.
+
+
+
+---
+
+## New React Features {/*new-react-features*/}
+
+### `` {/*activity*/}
+
+`` lets you break your app into "activities" that can be controlled and prioritized.
+
+You can use Activity as an alternative to conditionally rendering parts of your app:
+
+```js
+// Before
+{isVisible && }
+
+// After
+
+
+
+```
+
+In React 19.2, Activity supports two modes: `visible` and `hidden`.
+
+- `hidden`: hides the children, unmounts effects, and defers all updates until React has nothing left to work on.
+- `visible`: shows the children, mounts effects, and allows updates to be processed normally.
+
+This means you can pre-render and keep rendering hidden parts of the app without impacting the performance of anything visible on screen.
+
+You can use Activity to render hidden parts of the app that a user is likely to navigate to next, or to save the state of parts the user navigates away from. This helps make navigations quicker by loading data, css, and images in the background, and allows back navigations to maintain state such as input fields.
+
+In the future, we plan to add more modes to Activity for different use cases.
+
+For examples on how to use Activity, check out the [Activity docs](/reference/react/Activity).
+
+---
+
+### `useEffectEvent` {/*use-effect-event*/}
+
+One common pattern with `useEffect` is to notify the app code about some kind of "events" from an external system. For example, when a chat room gets connected, you might want to display a notification:
+
+```js {5,11}
+function ChatRoom({ roomId, theme }) {
+ useEffect(() => {
+ const connection = createConnection(serverUrl, roomId);
+ connection.on('connected', () => {
+ showNotification('Connected!', theme);
+ });
+ connection.connect();
+ return () => {
+ connection.disconnect()
+ };
+ }, [roomId, theme]);
+ // ...
+```
+
+The problem with the code above is that a change to any values used inside such an "event" will cause the surrounding Effect to re-run. For example, changing the `theme` will cause the chat room to reconnect. This makes sense for values related to the Effect logic itself, like `roomId`, but it doesn't make sense for `theme`.
+
+To solve this, most users just disable the lint rule and exclude the dependency. But that can lead to bugs since the linter can no longer help you keep the dependencies up to date if you need to update the Effect later.
+
+With `useEffectEvent`, you can split the "event" part of this logic out of the Effect that emits it:
+
+```js {2,3,4,9}
+function ChatRoom({ roomId, theme }) {
+ const onConnected = useEffectEvent(() => {
+ showNotification('Connected!', theme);
+ });
+
+ useEffect(() => {
+ const connection = createConnection(serverUrl, roomId);
+ connection.on('connected', () => {
+ onConnected();
+ });
+ connection.connect();
+ return () => connection.disconnect();
+ }, [roomId]); // ✅ All dependencies declared (Effect Events aren't dependencies)
+ // ...
+```
+
+Similar to DOM events, Effect Events always “see” the latest props and state.
+
+**Effect Events should _not_ be declared in the dependency array**. You'll need to upgrade to `eslint-plugin-react-hooks@latest` so that the linter doesn't try to insert them as dependencies. Note that Effect Events can only be declared in the same component or Hook as "their" Effect. These restrictions are verified by the linter.
+
+
+
+#### When to use `useEffectEvent` {/*when-to-use-useeffectevent*/}
+
+You should use `useEffectEvent` for functions that are conceptually "events" that happen to be fired from an Effect instead of a user event (that's what makes it an "Effect Event"). You don't need to wrap everything in `useEffectEvent`, or to use it just to silence the lint error, as this can lead to bugs.
+
+For a deep dive on how to think about Event Effects, see: [Separating Events from Effects](/learn/separating-events-from-effects#extracting-non-reactive-logic-out-of-effects).
+
+
+
+---
+
+### `cacheSignal` {/*cache-signal*/}
+
+
+
+`cacheSignal` is only for use with [React Server Components](/reference/rsc/server-components).
+
+
+
+`cacheSignal` allows you to know when the [`cache()`](/reference/react/cache) lifetime is over:
+
+```
+import {cache, cacheSignal} from 'react';
+const dedupedFetch = cache(fetch);
+
+async function Component() {
+ await dedupedFetch(url, { signal: cacheSignal() });
+}
+```
+
+This allows you to clean up or abort work when the result will no longer be used in the cache, such as:
+
+- React has successfully completed rendering
+- The render was aborted
+- The render has failed
+
+For more info, see the [`cacheSignal` docs](/reference/react/cacheSignal).
+
+---
+
+### Performance Tracks {/*performance-tracks*/}
+
+React 19.2 adds a new set of [custom tracks](https://developer.chrome.com/docs/devtools/performance/extension) to Chrome DevTools performance profiles to provide more information about the performance of your React app:
+
+
+
+
+
+
+
+
+
+
+
+
+The [React Performance Tracks docs](/reference/dev-tools/react-performance-tracks) explain everything included in the tracks, but here is a high-level overview.
+
+#### Scheduler ⚛ {/*scheduler-*/}
+
+The Scheduler track shows what React is working on for different priorities such as "blocking" for user interactions, or "transition" for updates inside startTransition. Inside each track, you will see the type of work being performed such as the event that scheduled an update, and when the render for that update happened.
+
+We also show information such as when an update is blocked waiting for a different priority, or when React is waiting for paint before continuing. The Scheduler track helps you understand how React splits your code into different priorities, and the order it completed the work.
+
+See the [Scheduler track](/reference/dev-tools/react-performance-tracks#scheduler) docs to see everything included.
+
+#### Components ⚛ {/*components-*/}
+
+The Components track shows the tree of components that React is working on either to render or run effects. Inside you'll see labels such as "Mount" for when children mount or effects are mounted, or "Blocked" for when rendering is blocked due to yielding to work outside React.
+
+The Components track helps you understand when components are rendered or run effects, and the time it takes to complete that work to help identify performance problems.
+
+See the [Components track docs](/reference/dev-tools/react-performance-tracks#components) for see everything included.
+
+---
+
+## New React DOM Features {/*new-react-dom-features*/}
+
+### Partial Pre-rendering {/*partial-pre-rendering*/}
+
+In 19.2 we're adding a new capability to pre-render part of the app ahead of time, and resume rendering it later.
+
+This feature is called "Partial Pre-rendering", and allows you to pre-render the static parts of your app and serve it from a CDN, and then resume rendering the shell to fill it in with dynamic content later.
+
+To pre-render an app to resume later, first call `prerender` with an `AbortController`:
+
+```
+const {prelude, postponed} = await prerender(, {
+ signal: controller.signal,
+});
+
+// Save the postponed state for later
+await savePostponedState(postponed);
+
+// Send prelude to client or CDN.
+```
+
+Then, you can return the `prelude` shell to the client, and later call `resume` to "resume" to a SSR stream:
+
+```
+const postponed = await getPostponedState(request);
+const resumeStream = await resume(, postponed);
+
+// Send stream to client.
+```
+
+Or you can call `resumeAndPrerender` to resume to get static HTML for SSG:
+
+```
+const postponedState = await getPostponedState(request);
+const { prelude } = await resumeAndPrerender(, postponedState);
+
+// Send complete HTML prelude to CDN.
+```
+
+For more info, see the docs for the new APIs:
+- `react-dom/server`
+ - [`resume`](/reference/react-dom/server/resume): for Web Streams.
+ - [`resumeToPipeableStream`](/reference/react-dom/server/resumeToPipeableStream) for Node Streams.
+- `react-dom/static`
+ - [`resumeAndPrerender`](/reference/react-dom/static/resumeAndPrerender) for Web Streams.
+ - [`resumeAndPrerenderToNodeStream`](/reference/react-dom/static/resumeAndPrerenderToNodeStream) for Node Streams.
+
+Additionally, the prerender apis now return a `postpone` state to pass to the `resume` apis.
+
+---
+
+## Notable Changes {/*notable-changes*/}
+
+### Batching Suspense Boundaries for SSR {/*batching-suspense-boundaries-for-ssr*/}
+
+We fixed a behavioral bug where Suspense boundaries would reveal differently depending on if they were rendered on the client or when streaming from server-side rendering.
+
+Starting in 19.2, React will batch reveals of server-rendered Suspense boundaries for a short time, to allow more content to be revealed together and align with the client-rendered behavior.
+
+
+
+Previously, during streaming server-side rendering, suspense content would immediately replace fallbacks.
+
+
+
+
+
+In React 19.2, suspense boundaries are batched for a small amount of time, to allow revealing more content together.
+
+
+
+This fix also prepares apps for supporting `` for Suspense during SSR. By revealing more content together, animations can run in larger batches of content, and avoid chaining animations of content that stream in close together.
+
+
+
+React uses heuristics to ensure throttling does not impact core web vitals and search ranking.
+
+For example, if the total page load time is approaching 2.5s (which is the time considered "good" for [LCP](https://web.dev/articles/lcp)), React will stop batching and reveal content immediately so that the throttling is not the reason to miss the metric.
+
+
+
+---
+
+### SSR: Web Streams support for Node {/*ssr-web-streams-support-for-node*/}
+
+React 19.2 adds support for Web Streams for streaming SSR in Node.js:
+- [`renderToReadableStream`](/reference/react-dom/server/renderToReadableStream) is now available for Node.js
+- [`prerender`](/reference/react-dom/static/prerender) is now available for Node.js
+
+As well as the new `resume` APIs:
+- [`resume`](/reference/react-dom/server/resume) is available for Node.js.
+- [`resumeAndPrerender`](/reference/react-dom/static/resumeAndPrerender) is available for Node.js.
+
+
+
+
+#### Prefer Node Streams for server-side rendering in Node.js {/*prefer-node-streams-for-server-side-rendering-in-nodejs*/}
+
+In Node.js environments, we still highly recommend using the Node Streams APIs:
+
+- [`renderToPipeableStream`](/reference/react-dom/server/renderToPipeableStream)
+- [`resumeToPipeableStream`](/reference/react-dom/server/resumeToPipeableStream)
+- [`prerenderToNodeStream`](/reference/react-dom/static/prerenderToNodeStream)
+- [`resumeAndPrerenderToNodeStream`](/reference/react-dom/static/resumeAndPrerenderToNodeStream)
+
+This is because Node Streams are much faster than Web Streams in Node, and Web Streams do not support compression by default, leading to users accidentally missing the benefits of streaming.
+
+
+
+---
+
+### `eslint-plugin-react-hooks` v6 {/*eslint-plugin-react-hooks*/}
+
+We also published `eslint-plugin-react-hooks@latest` with flat config by default in the `recommended` preset, and opt-in for new React Compiler powered rules.
+
+To continue using the legacy config, you can change to `recommended-legacy`:
+
+```diff
+- extends: ['plugin:react-hooks/recommended']
++ extends: ['plugin:react-hooks/recommended-legacy']
+```
+
+For a full list of compiler enabled rules, [check out the linter docs](/reference/eslint-plugin-react-hooks#recommended).
+
+Check out the `eslint-plugin-react-hooks` [changelog for a full list of changes](https://github.com/facebook/react/blob/main/packages/eslint-plugin-react-hooks/CHANGELOG.md#610).
+
+---
+
+### Update the default `useId` prefix {/*update-the-default-useid-prefix*/}
+
+In 19.2, we're updating the default `useId` prefix from `:r:` (19.0.0) or `«r»` (19.1.0) to `_r_`.
+
+The original intent of using a special character that was not valid for CSS selectors was that it would be unlikely to collide with IDs written by users. However, to support View Transitions, we need to ensure that IDs generated by `useId` are valid for `view-transition-name` and XML 1.0 names.
+
+---
+
+## Changelog {/*changelog*/}
+
+Other notable changes
+- `react-dom`: Allow nonce to be used on hoistable styles [#32461](https://github.com/facebook/react/pull/32461)
+- `react-dom`: Warn for using a React owned node as a Container if it also has text content [#32774](https://github.com/facebook/react/pull/32774)
+
+Notable bug fixes
+- `react`: Stringify context as "SomeContext" instead of "SomeContext.Provider" [#33507](https://github.com/facebook/react/pull/33507)
+- `react`: Fix infinite useDeferredValue loop in popstate event [#32821](https://github.com/facebook/react/pull/32821)
+- `react`: Fix a bug when an initial value was passed to useDeferredValue [#34376](https://github.com/facebook/react/pull/34376)
+- `react`: Fix a crash when submitting forms with Client Actions [#33055](https://github.com/facebook/react/pull/33055)
+- `react`: Hide/unhide the content of dehydrated suspense boundaries if they resuspend [#32900](https://github.com/facebook/react/pull/32900)
+- `react`: Avoid stack overflow on wide trees during Hot Reload [#34145](https://github.com/facebook/react/pull/34145)
+- `react`: Improve component stacks in various places [#33629](https://github.com/facebook/react/pull/33629), [#33724](https://github.com/facebook/react/pull/33724), [#32735](https://github.com/facebook/react/pull/32735), [#33723](https://github.com/facebook/react/pull/33723)
+- `react`: Fix a bug with React.use inside React.lazy-ed Component [#33941](https://github.com/facebook/react/pull/33941)
+- `react-dom`: Stop warning when ARIA 1.3 attributes are used [#34264](https://github.com/facebook/react/pull/34264)
+- `react-dom`: Fix a bug with deeply nested Suspense inside Suspense fallbacks [#33467](https://github.com/facebook/react/pull/33467)
+- `react-dom`: Avoid hanging when suspending after aborting while rendering [#34192](https://github.com/facebook/react/pull/34192)
+
+For a full list of changes, please see the [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md).
+
+
+---
+
+_Thanks to [Ricky Hanlon](https://bsky.app/profile/ricky.fm) for [writing this post](https://www.youtube.com/shorts/T9X3YkgZRG0), [Dan Abramov](https://bsky.app/profile/danabra.mov), [Matt Carroll](https://twitter.com/mattcarrollcode), [Jack Pope](https://jackpope.me), and [Joe Savona](https://x.com/en_JS) for reviewing this post._
diff --git a/src/content/blog/2025/10/07/introducing-the-react-foundation.md b/src/content/blog/2025/10/07/introducing-the-react-foundation.md
new file mode 100644
index 0000000000..a9b922dbc9
--- /dev/null
+++ b/src/content/blog/2025/10/07/introducing-the-react-foundation.md
@@ -0,0 +1,67 @@
+---
+title: "Introducing the React Foundation"
+author: Seth Webster, Matt Carroll, Joe Savona
+date: 2025/10/07
+description: Today, we're announcing our plans to create the React Foundation a new technical governance structure
+---
+
+October 7, 2025 by [Seth Webster](https://x.com/sethwebster), [Matt Carroll](https://x.com/mattcarrollcode), [Joe Savona](https://x.com/en_JS), [Sophie Alpert](https://x.com/sophiebits)
+
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Today, we're announcing our plans to create the React Foundation and a new technical governance structure.
+
+
+
+---
+
+We open sourced React over a decade ago to help developers build great user experiences. From its earliest days, React has received substantial contributions from contributors outside of Meta. Over time, the number of contributors and the scope of their contributions has grown significantly. What started out as a tool developed for Meta has expanded into a project that spans multiple companies with regular contributions from across the ecosystem. React has outgrown the confines of any one company.
+
+To better serve the React community, we are announcing our plans to move React and React Native from Meta to a new React Foundation. As a part of this change, we will also be implementing a new independent technical governance structure. We believe these changes will enable us to give React ecosystem projects more resources.
+
+## The React Foundation {/*the-react-foundation*/}
+
+We will make the React Foundation the new home for React, React Native, and some supporting projects like JSX. The React Foundation’s mission will be to support the React community and ecosystem. Once implemented, the React Foundation will
+
+* Maintain React’s infrastructure like GitHub, CI, and trademarks
+* Organize React Conf
+* Create initiatives to support the React ecosystem like financial support of ecosystem projects, issuing grants, and creating programs
+
+The React Foundation will be governed by a board of directors, with Seth Webster serving as the executive director. This board will direct funds and resources to support React’s development, community, and ecosystem. We believe that this is the best structure to ensure that the React Foundation is vendor-neutral and reflects the best interests of the community.
+
+The founding corporate members of the React Foundation will be Amazon, Callstack, Expo, Meta, Microsoft, Software Mansion, and Vercel. These companies have had a major impact on the React and React Native ecosystems and we are grateful for their support. We are excited to welcome even more members in the future.
+
+
+
+
+
+
+
+
+
+
+
+
+## React’s technical governance {/*reacts-technical-governance*/}
+
+We believe that React's technical direction should be set by the people who contribute to and maintain React. As React moves to a foundation, it is important that no single company or organization is overrepresented. To achieve this, we plan to define a new technical governance structure for React that is independent from the React Foundation.
+
+As a part of creating React’s new technical governance structure we will reach out to the community for feedback. Once finalized, we will share details in a future post.
+
+## Thank you {/*thank-you*/}
+
+React's incredible growth is thanks to the thousands of people, companies, and projects that have shaped React. The creation of the React Foundation is a testament to the strength and vibrancy of the React community. Together, the React Foundation and React’s new technical governance will ensure that React’s future is secure for years to come.
diff --git a/src/content/blog/2025/10/07/react-compiler-1.md b/src/content/blog/2025/10/07/react-compiler-1.md
new file mode 100644
index 0000000000..5474c50d3f
--- /dev/null
+++ b/src/content/blog/2025/10/07/react-compiler-1.md
@@ -0,0 +1,194 @@
+---
+title: "React Compiler v1.0"
+author: Lauren Tan, Joe Savona, and Mofei Zhang
+date: 2025/10/07
+description: We are releasing the compiler's first stable release today.
+
+---
+
+Oct 7, 2025 by [Lauren Tan](https://x.com/potetotes), [Joe Savona](https://x.com/en_JS), and [Mofei Zhang](https://x.com/zmofei).
+
+---
+
+
+
+The React team is excited to share new updates:
+
+
+
+1. React Compiler 1.0 is available today.
+2. Compiler-powered lint rules ship in `eslint-plugin-react-hooks`'s `recommended` and `recommended-latest` preset.
+3. We've published an incremental adoption guide, and partnered with Expo, Vite, and Next.js so new apps can start with the compiler enabled.
+
+---
+
+We are releasing the compiler's first stable release today. React Compiler works on both React and React Native, and automatically optimizes components and hooks without requiring rewrites. The compiler has been battle tested on major apps at Meta and is fully production-ready.
+
+[React Compiler](/learn/react-compiler) is a build-time tool that optimizes your React app through automatic memoization. Last year, we published React Compiler's [first beta](/blog/2024/10/21/react-compiler-beta-release) and received lots of great feedback and contributions. We're excited about the wins we've seen from folks adopting the compiler (see case studies from [Sanity Studio](https://github.com/reactwg/react-compiler/discussions/33) and [Wakelet](https://github.com/reactwg/react-compiler/discussions/52)) and are excited to bring the compiler to more users in the React community.
+
+This release is the culmination of a huge and complex engineering effort spanning almost a decade. The React team's first exploration into compilers started with [Prepack](https://github.com/facebookarchive/prepack) in 2017. While this project was eventually shut down, there were many learnings that informed the team on the design of Hooks, which were designed with a future compiler in mind. In 2021, [Xuan Huang](https://x.com/Huxpro) demoed the [first iteration](https://www.youtube.com/watch?v=lGEMwh32soc) of a new take on React Compiler.
+
+Although this first version of the new React Compiler was eventually rewritten, the first prototype gave us increased confidence that this was a tractable problem, and the learnings that an alternative compiler architecture could precisely give us the memoization characteristics we wanted. [Joe Savona](https://x.com/en_JS), [Sathya Gunasekaran](https://x.com/_gsathya), [Mofei Zhang](https://x.com/zmofei), and [Lauren Tan](https://x.com/potetotes) worked through our first rewrite, moving the compiler's architecture into a Control Flow Graph (CFG) based High-Level Intermediate Representation (HIR). This paved the way for much more precise analysis and even type inference within React Compiler. Since then, many significant portions of the compiler have been rewritten, with each rewrite informed by our learnings from the previous attempt. And we have received significant help and contributions from many members of the [React team](/community/team) along the way.
+
+This stable release is our first of many. The compiler will continue to evolve and improve, and we expect to see it become a new foundation and era for the next decade and more of React.
+
+You can jump straight to the [quickstart](/learn/react-compiler), or read on for the highlights from React Conf 2025.
+
+
+
+#### How does React Compiler work? {/*how-does-react-compiler-work*/}
+
+React Compiler is an optimizing compiler that optimizes components and hooks through automatic memoization. While it is implemented as a Babel plugin currently, the compiler is largely decoupled from Babel and lowers the Abstract Syntax Tree (AST) provided by Babel into its own novel HIR, and through multiple compiler passes, carefully understands data-flow and mutability of your React code. This allows the compiler to granularly memoize values used in rendering, including the ability to memoize conditionally, which is not possible through manual memoization.
+
+```js {8}
+import { use } from 'react';
+
+export default function ThemeProvider(props) {
+ if (!props.children) {
+ return null;
+ }
+ // The compiler can still memoize code after a conditional return
+ const theme = mergeTheme(props.theme, use(ThemeContext));
+ return (
+
+ {props.children}
+
+ );
+}
+```
+_See this example in the [React Compiler Playground](https://playground.react.dev/#N4Igzg9grgTgxgUxALhASwLYAcIwC4AEwBUYCBAvgQGYwQYEDkMCAhnHowNwA6AdvwQAPHPgIATBNVZQANoWpQ+HNBD4EAKgAsEGBAAU6ANzSSYACix0sYAJRF+BAmmoFzAQisQbAOjha0WXEWPntgRycCFjxYdT45WV51Sgi4NTBCPB09AgBeAj0YAHMEbV0ES2swHyzygBoSMnMyvQBhNTxhPFtbJKdo2LcIpwAeFoR2vk6hQiNWWSgEXOBavQoAPmHI4C9ff0DghD4KLZGAenHJ6bxN5N7+ChA6kDS+ajQilHRsXEyATyw5GI+gWRTQfAA8lg8Ko+GBKDQ6AxGAAjVgohCyAC0WFB4KxLHYeCxaWwgQQMDO4jQGW4-H45nCyTOZ1JWECrBhagAshBJMgCDwQPNZEKHgQwJyae8EPCQVAwZDobC7FwnuAtBAAO4ASSmFL48zAKGksjIFCAA)_
+
+In addition to automatic memoization, React Compiler also has validation passes that run on your React code. These passes encode the [Rules of React](/reference/rules), and uses the compiler's understanding of data-flow and mutability to provide diagnostics where the Rules of React are broken. These diagnostics often expose latent bugs hiding in React code, and are primarily surfaced through `eslint-plugin-react-hooks`.
+
+To learn more about how the compiler optimizes your code, visit the [Playground](https://playground.react.dev).
+
+
+
+## Use React Compiler Today {/*use-react-compiler-today*/}
+To install the compiler:
+
+npm
+
+{`npm install --save-dev --save-exact babel-plugin-react-compiler@latest`}
+
+
+pnpm
+
+{`pnpm add --save-dev --save-exact babel-plugin-react-compiler@latest`}
+
+
+yarn
+
+{`yarn add --dev --exact babel-plugin-react-compiler@latest`}
+
+
+As part of the stable release, we've been making React Compiler easier to add to your projects and added optimizations to how the compiler generates memoization. React Compiler now supports optional chains and array indices as dependencies. These improvements ultimately result in fewer re-renders and more responsive UIs, while letting you keep writing idiomatic declarative code.
+
+You can find more details on using the Compiler in [our docs](/learn/react-compiler).
+
+## What we're seeing in production {/*react-compiler-at-meta*/}
+[The compiler has already shipped in apps like Meta Quest Store](https://youtu.be/lyEKhv8-3n0?t=3002). We've seen initial loads and cross-page navigations improve by up to 12%, while certain interactions are more than 2.5× faster. Memory usage stays neutral even with these wins. Although your mileage may vary, we recommend experimenting with the compiler in your app to see similar performance gains.
+
+## Backwards Compatibility {/*backwards-compatibility*/}
+As noted in the Beta announcement, React Compiler is compatible with React 17 and up. If you are not yet on React 19, you can use React Compiler by specifying a minimum target in your compiler config, and adding `react-compiler-runtime` as a dependency. You can find docs on this [here](/reference/react-compiler/target#targeting-react-17-or-18).
+
+## Enforce the Rules of React with compiler-powered linting {/*migrating-from-eslint-plugin-react-compiler-to-eslint-plugin-react-hooks*/}
+React Compiler includes an ESLint rule that helps identify code that breaks the [Rules of React](/reference/rules). The linter does not require the compiler to be installed, so there's no risk in upgrading eslint-plugin-react-hooks. We recommend everyone upgrade today.
+
+If you have already installed `eslint-plugin-react-compiler`, you can now remove it and use `eslint-plugin-react-hooks@latest`. Many thanks to [@michaelfaith](https://bsky.app/profile/michael.faith) for contributing to this improvement!
+
+To install:
+
+npm
+
+{`npm install --save-dev eslint-plugin-react-hooks@latest`}
+
+
+pnpm
+
+{`pnpm add --save-dev eslint-plugin-react-hooks@latest`}
+
+
+yarn
+
+{`yarn add --dev eslint-plugin-react-hooks@latest`}
+
+
+```js {6}
+// eslint.config.js (Flat Config)
+import reactHooks from 'eslint-plugin-react-hooks';
+import { defineConfig } from 'eslint/config';
+
+export default defineConfig([
+ reactHooks.configs.flat.recommended,
+]);
+```
+
+```js {3}
+// eslintrc.json (Legacy Config)
+{
+ "extends": ["plugin:react-hooks/recommended"],
+ // ...
+}
+```
+
+To enable React Compiler rules, we recommend using the `recommended` preset. You can also check out the [README](https://github.com/facebook/react/blob/main/packages/eslint-plugin-react-hooks/README.md) for more instructions. Here are a few examples we featured at React Conf:
+
+- Catching `setState` patterns that cause render loops with [`set-state-in-render`](/reference/eslint-plugin-react-hooks/lints/set-state-in-render).
+- Flagging expensive work inside effects via [`set-state-in-effect`](/reference/eslint-plugin-react-hooks/lints/set-state-in-effect).
+- Preventing unsafe ref access during render with [`refs`](/reference/eslint-plugin-react-hooks/lints/refs).
+
+## What should I do about useMemo, useCallback, and React.memo? {/*what-should-i-do-about-usememo-usecallback-and-reactmemo*/}
+By default, React Compiler will memoize your code based on its analysis and heuristics. In most cases, this memoization will be as precise, or moreso, than what you may have written — and as noted above, the compiler can memoize even in cases where `useMemo`/`useCallback` cannot be used, such as after an early return.
+
+However, in some cases developers may need more control over memoization. The `useMemo` and `useCallback` hooks can continue to be used with React Compiler as an escape hatch to provide control over which values are memoized. A common use-case for this is if a memoized value is used as an effect dependency, in order to ensure that an effect does not fire repeatedly even when its dependencies do not meaningfully change.
+
+For new code, we recommend relying on the compiler for memoization and using `useMemo`/`useCallback` where needed to achieve precise control.
+
+For existing code, we recommend either leaving existing memoization in place (removing it can change compilation output) or carefully testing before removing the memoization.
+
+## New apps should use React Compiler {/*new-apps-should-use-react-compiler*/}
+We have partnered with the Expo, Vite, and Next.js teams to add the compiler to the new app experience.
+
+[Expo SDK 54](https://docs.expo.dev/guides/react-compiler/) and up has the compiler enabled by default, so new apps will automatically be able to take advantage of the compiler from the start.
+
+
+{`npx create-expo-app@latest`}
+
+
+[Vite](https://vite.dev/guide/) and [Next.js](https://nextjs.org/docs/app/api-reference/cli/create-next-app) users can choose the compiler enabled templates in `create-vite` and `create-next-app`.
+
+
+{`npm create vite@latest`}
+
+
+
+
+
+{`npx create-next-app@latest`}
+
+
+## Adopt React Compiler incrementally {/*adopt-react-compiler-incrementally*/}
+If you're maintaining an existing application, you can roll out the compiler at your own pace. We published a step-by-step [incremental adoption guide](/learn/react-compiler/incremental-adoption) that covers gating strategies, compatibility checks, and rollout tooling so you can enable the compiler with confidence.
+
+## swc support (experimental) {/*swc-support-experimental*/}
+React Compiler can be installed across [several build tools](/learn/react-compiler#installation) such as Babel, Vite, and Rsbuild.
+
+In addition to those tools, we have been collaborating with Kang Dongyoon ([@kdy1dev](https://x.com/kdy1dev)) from the [swc](https://swc.rs/) team on adding additional support for React Compiler as an swc plugin. While this work isn't done, Next.js build performance should now be considerably faster when the [React Compiler is enabled in your Next.js app](https://nextjs.org/docs/app/api-reference/config/next-config-js/reactCompiler).
+
+We recommend using Next.js [15.3.1](https://github.com/vercel/next.js/releases/tag/v15.3.1) or greater to get the best build performance.
+
+Vite users can continue to use [vite-plugin-react](https://github.com/vitejs/vite-plugin-react) to enable the compiler, by adding it as a [Babel plugin](/learn/react-compiler/installation#vite). We are also working with the [oxc](https://oxc.rs/) team to [add support for the compiler](https://github.com/oxc-project/oxc/issues/10048). Once [rolldown](https://github.com/rolldown/rolldown) is officially released and supported in Vite and oxc support is added for React Compiler, we'll update the docs with information on how to migrate.
+
+## Upgrading React Compiler {/*upgrading-react-compiler*/}
+React Compiler works best when the auto-memoization applied is strictly for performance. Future versions of the compiler may change how memoization is applied, for example it could become more granular and precise.
+
+However, because product code may sometimes break the [rules of React](/reference/rules) in ways that aren't always statically detectable in JavaScript, changing memoization can occasionally have unexpected results. For example, a previously memoized value might be used as a dependency for a `useEffect` somewhere in the component tree. Changing how or whether this value is memoized can cause over or under-firing of that `useEffect`. While we encourage [useEffect only for synchronization](/learn/synchronizing-with-effects), your codebase may have `useEffect`s that cover other use cases, such as effects that needs to only run in response to specific values changing.
+
+In other words, changing memoization may under rare circumstances cause unexpected behavior. For this reason, we recommend following the Rules of React and employing continuous end-to-end testing of your app so you can upgrade the compiler with confidence and identify any rules of React violations that might cause issues.
+
+If you don't have good test coverage, we recommend pinning the compiler to an exact version (eg `1.0.0`) rather than a SemVer range (eg `^1.0.0`). You can do this by passing the `--save-exact` (npm/pnpm) or `--exact` flags (yarn) when upgrading the compiler. You should then do any upgrades of the compiler manually, taking care to check that your app still works as expected.
+
+---
+
+Thanks to [Jason Bonta](https://x.com/someextent), [Jimmy Lai](https://x.com/feedthejim), [Kang Dongyoon](https://x.com/kdy1dev) (@kdy1dev), and [Dan Abramov](https://bsky.app/profile/danabra.mov) for reviewing and editing this post.
diff --git a/src/content/blog/index.md b/src/content/blog/index.md
index 2c19a3a860..b969b34c1f 100644
--- a/src/content/blog/index.md
+++ b/src/content/blog/index.md
@@ -11,15 +11,31 @@ title: React Blog
-
+
-In React Labs posts, we write about projects in active research and development. In this post, we're sharing two new experimental features that are ready to try today, and sharing other areas we're working on now ...
+We're releasing the compiler's first stable release today, plus linting and tooling improvements to make adoption easier.
-
+
+<<<<<<< HEAD
我们今天将发布 React Compiler 的第一个候选发布版(RC)。
+=======
+Today, we're announcing our plans to create the React Foundation and a new technical governance structure ...
+
+
+
+
+
+React 19.2 adds new features like Activity, React Performance Tracks, useEffectEvent, and more. In this post ...
+
+
+
+
+
+In React Labs posts, we write about projects in active research and development. In this post, we're sharing two new experimental features that are ready to try today, and sharing other areas we're working on now ...
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
diff --git a/src/content/errors/index.md b/src/content/errors/index.md
index 09610a40da..4226fd25b6 100644
--- a/src/content/errors/index.md
+++ b/src/content/errors/index.md
@@ -6,4 +6,10 @@
我们强烈建议你在本地调试应用时使用开发环境构建,因为它会追踪额外的调试信息,并针对应用中的潜在问题提供有用的警告。但是,如果你在使用生产环境构建时遇到异常,错误信息将只包含一个指向相关错误文档的链接。
+<<<<<<< HEAD
参阅 [https://react.dev/errors/149](/errors/421) 查看示例。
+=======
+We highly recommend using the development build locally when debugging your app since it tracks additional debug info and provides helpful warnings about potential problems in your apps, but if you encounter an exception while using the production build, the error message will include just a link to the docs for the error.
+
+For an example, see: [https://react.dev/errors/149](/errors/149).
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
diff --git a/src/content/learn/escape-hatches.md b/src/content/learn/escape-hatches.md
index e54b0dc6d7..e1eec8a456 100644
--- a/src/content/learn/escape-hatches.md
+++ b/src/content/learn/escape-hatches.md
@@ -312,6 +312,7 @@ React 提供了检查工具规则来检查是否正确地指定了 Effect 的依
## 将事件从 Effect 中分开 {/*separating-events-from-effects*/}
+<<<<<<< HEAD
本节描述了一个在稳定版本的 React 中 **尚未发布** 的实验性 API。
@@ -319,6 +320,9 @@ React 提供了检查工具规则来检查是否正确地指定了 Effect 的依
事件处理程序仅在再次执行相同的交互时重新运行。与事件处理程序不同,如果 Effect 读取的任何值(如 props 或 state)与上次渲染期间不同,则会重新同步。有时,需要混合两种行为:Effect 重新运行以响应某些值而不是其他值。
+=======
+Event handlers only re-run when you perform the same interaction again. Unlike event handlers, Effects re-synchronize if any of the values they read, like props or state, are different than during last render. Sometimes, you want a mix of both behaviors: an Effect that re-runs in response to some values but not others.
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
Effect 中的所有代码都是 **响应式的**。如果它读取的某些响应式的值由于重新渲染而发生变化,它将再次运行。例如,如果 `roomId` 或 `theme` 发生变化,这个 Effect 将重新连接到聊天:
@@ -455,8 +459,8 @@ label { display: block; margin-top: 10px; }
```json package.json hidden
{
"dependencies": {
- "react": "canary",
- "react-dom": "canary",
+ "react": "latest",
+ "react-dom": "latest",
"react-scripts": "latest",
"toastify-js": "1.12.0"
},
diff --git a/src/content/learn/react-compiler/installation.md b/src/content/learn/react-compiler/installation.md
index 65fff4ea04..daf56fb1bf 100644
--- a/src/content/learn/react-compiler/installation.md
+++ b/src/content/learn/react-compiler/installation.md
@@ -18,28 +18,32 @@ title: 安装
React 编译器专为与 React 19 配合使用而设计,但也支持 React 17 和 18。了解有关 [React 版本兼容性](/reference/react-compiler/target) 的更多信息。
+<<<<<<< HEAD
React Compiler 当前处于 RC 阶段。请使用 `@rc` 标签安装,以获取最新的发布候选版本。
## 安装 {/*installation*/}
+=======
+## Installation {/*installation*/}
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
将 React 编译器安装为 `devDependency`:
-npm install -D babel-plugin-react-compiler@rc
+npm install -D babel-plugin-react-compiler@latest
或者使用 Yarn:
-yarn add -D babel-plugin-react-compiler@rc
+yarn add -D babel-plugin-react-compiler@latest
或者使用 pnpm:
-pnpm install -D babel-plugin-react-compiler@rc
+pnpm install -D babel-plugin-react-compiler@latest
## 基本设置 {/*basic-setup*/}
@@ -173,10 +177,14 @@ React Compiler 包含一条 ESLint 规则,可帮助识别无法优化的代码
安装 ESLint 插件:
-npm install -D eslint-plugin-react-hooks@rc
+npm install -D eslint-plugin-react-hooks@latest
+<<<<<<< HEAD
如果你尚未配置好 eslint-plugin-react-hooks,参考 [readme 的安装说明来进行配置](https://github.com/facebook/react/blob/main/packages/eslint-plugin-react-hooks/README.md#installation)。最新的 RC 版本中默认启用了编译器规则,因此不需要其他配置。
+=======
+If you haven't already configured eslint-plugin-react-hooks, follow the [installation instructions in the readme](https://github.com/facebook/react/blob/main/packages/eslint-plugin-react-hooks/README.md#installation). The compiler rules are available in the `recommended-latest` preset.
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
ESLint 规则将会:
- 识别对 [React 规则](/reference/rules) 的违反情况
@@ -242,8 +250,16 @@ function ProblematicComponent() {
既然你已经安装了 React 编译器,可以进一步了解以下内容:
+<<<<<<< HEAD
- [React 版本兼容性](/reference/react-compiler/target),适用于 React 17 和 18
- [配置选项](/reference/react-compiler/configuration),用于自定义编译器
- [渐进采用策略](/learn/react-compiler/incremental-adoption),用于现有的代码库
- [调试技巧](/learn/react-compiler/debugging),用于排查问题
- [编译库指南](/reference/react-compiler/compiling-libraries),用于编译你的 React 库
+=======
+- [React version compatibility](/reference/react-compiler/target) for React 17 and 18
+- [Configuration options](/reference/react-compiler/configuration) to customize the compiler
+- [Incremental adoption strategies](/learn/react-compiler/incremental-adoption) for existing codebases
+- [Debugging techniques](/learn/react-compiler/debugging) for troubleshooting issues
+- [Compiling Libraries guide](/reference/react-compiler/compiling-libraries) for compiling your React library
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
diff --git a/src/content/learn/react-compiler/introduction.md b/src/content/learn/react-compiler/introduction.md
index 65d1ac66e8..1550148af2 100644
--- a/src/content/learn/react-compiler/introduction.md
+++ b/src/content/learn/react-compiler/introduction.md
@@ -16,11 +16,15 @@ React Compiler 是一个新的构建时工具,它可以自动优化你的 Reac
+<<<<<<< HEAD
React Compiler 目前处于发布候选(RC)阶段。我们现在建议所有人尝试使用该编译器并提供反馈。最新的 RC 版本可以通过 `@rc` 标签找到。
## React 编译器是做什么的? {/*what-does-react-compiler-do*/}
+=======
+## What does React Compiler do? {/*what-does-react-compiler-do*/}
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
React Compiler 会在构建时自动优化你的 React 应用。通常情况下,即使不进行优化,React 的性能也已经足够快,但有时你需要手动对组件和值进行记忆化(memoization)以保持应用的响应速度。这种手动记忆化既繁琐又容易出错,并且会增加需要维护的额外代码。React Compiler 为你自动完成这些优化,减轻了你的思维负担,使你可以专注于功能的开发。
@@ -28,7 +32,7 @@ React Compiler 会在构建时自动优化你的 React 应用。通常情况下
没有编译器的情况下,你需要手动对组件和值进行记忆化以优化重新渲染:
-```js {expectedErrors: {'react-compiler': [4]}}
+```js
import { useMemo, useCallback, memo } from 'react';
const ExpensiveComponent = memo(function ExpensiveComponent({ data, onClick }) {
@@ -156,7 +160,11 @@ So if `expensivelyProcessAReallyLargeArrayOfObjects` was used in many different
### 使用起来安全吗? {/*is-it-safe-to-use*/}
+<<<<<<< HEAD
React 编译器目前已进入 RC 阶段,并已在生产环境中进行了广泛测试。虽然像 Meta 这样的公司已经在生产中使用了它,但是否将编译器部署到你的应用程序生产环境,将取决于你的代码库状况以及你对 [React 规则](/reference/rules) 的遵循程度。
+=======
+React Compiler is now stable and has been tested extensively in production. While it has been used in production at companies like Meta, rolling out the compiler to production for your app will depend on the health of your codebase and how well you've followed the [Rules of React](/reference/rules).
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
## 支持哪些构建工具? {/*what-build-tools-are-supported*/}
@@ -168,9 +176,19 @@ Next.js 用户可以通过使用 [v15.3.1](https://github.com/vercel/next.js/rel
## 关于 useMemo、useCallback 和 React.memo 我应该怎么做? {/*what-should-i-do-about-usememo-usecallback-and-reactmemo*/}
+<<<<<<< HEAD
React 编译器能够比手动使用 [`useMemo`](/reference/react/useMemo)、[`useCallback`](/reference/react/useCallback) 和 [`React.memo`](/reference/react/memo) 更精确和细致地添加自动记忆化。如果你选择保留手动记忆化,React 编译器会分析它们,并判断你的手动记忆化是否与其自动推断出的记忆化一致。如果不一致,编译器将选择放弃优化该组件。
这样做是出于谨慎考虑,因为手动记忆化常见的反模式是为了保证程序的正确性。这意味着你的应用依赖于对特定值进行记忆化才能正常运行。例如,为了防止无限循环,你可能会记忆某些值来阻止 `useEffect` 被触发。这违反了 React 的规则,但因为编译器自动移除手动记忆化可能会有潜在危险,所以会直接放弃优化。你应该手动移除自己的手动记忆化代码,并验证应用是否仍能按预期运行。
+=======
+By default, React Compiler will memoize your code based on its analysis and heuristics. In most cases, this memoization will be as precise, or moreso, than what you may have written.
+
+However, in some cases developers may need more control over memoization. The `useMemo` and `useCallback` hooks can continue to be used with React Compiler as an escape hatch to provide control over which values are memoized. A common use-case for this is if a memoized value is used as an effect dependency, in order to ensure that an effect does not fire repeatedly even when its dependencies do not meaningfully change.
+
+For new code, we recommend relying on the compiler for memoization and using `useMemo`/`useCallback` where needed to achieve precise control.
+
+For existing code, we recommend either leaving existing memoization in place (removing it can change compilation output) or carefully testing before removing the memoization.
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
## 尝试 React 编译器 {/*try-react-compiler*/}
diff --git a/src/content/learn/removing-effect-dependencies.md b/src/content/learn/removing-effect-dependencies.md
index 5ffb55aae5..82d1ec666d 100644
--- a/src/content/learn/removing-effect-dependencies.md
+++ b/src/content/learn/removing-effect-dependencies.md
@@ -610,6 +610,7 @@ function ChatRoom({ roomId }) {
### 你想读取一个值而不对其变化做出“反应”吗? {/*do-you-want-to-read-a-value-without-reacting-to-its-changes*/}
+<<<<<<< HEAD
**`useEffectEvent` API 当前仅在 React Canary 和 实验发行版中可用**。
@@ -619,6 +620,9 @@ function ChatRoom({ roomId }) {
假设你希望在用户收到新消息时播放声音,`isMuted` 为 `true` 除外:
+=======
+Suppose that you want to play a sound when the user receives a new message unless `isMuted` is `true`:
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
```js {3,10-12}
function ChatRoom({ roomId }) {
@@ -1260,22 +1264,6 @@ Effect 中是否有一行代码不应该是响应式的?如何将非响应式
-```json package.json hidden
-{
- "dependencies": {
- "react": "canary",
- "react-dom": "canary",
- "react-scripts": "latest"
- },
- "scripts": {
- "start": "react-scripts start",
- "build": "react-scripts build",
- "test": "react-scripts test --env=jsdom",
- "eject": "react-scripts eject"
- }
-}
-```
-
```js
import { useState, useEffect, useRef } from 'react';
import { useEffectEvent } from 'react';
@@ -1387,22 +1375,6 @@ Effect 需要读取 `duration` 的最新值,但你不希望它对 `duration`
-```json package.json hidden
-{
- "dependencies": {
- "react": "canary",
- "react-dom": "canary",
- "react-scripts": "latest"
- },
- "scripts": {
- "start": "react-scripts start",
- "build": "react-scripts build",
- "test": "react-scripts test --env=jsdom",
- "eject": "react-scripts eject"
- }
-}
-```
-
```js
import { useState, useEffect, useRef } from 'react';
import { FadeInAnimation } from './animation.js';
@@ -1826,8 +1798,8 @@ label, button { display: block; margin-bottom: 5px; }
```json package.json hidden
{
"dependencies": {
- "react": "canary",
- "react-dom": "canary",
+ "react": "latest",
+ "react-dom": "latest",
"react-scripts": "latest",
"toastify-js": "1.12.0"
},
@@ -2121,8 +2093,8 @@ export default function ChatRoom({ roomId, isEncrypted, onMessage }) { // Reacti
```json package.json hidden
{
"dependencies": {
- "react": "canary",
- "react-dom": "canary",
+ "react": "latest",
+ "react-dom": "latest",
"react-scripts": "latest",
"toastify-js": "1.12.0"
},
diff --git a/src/content/learn/reusing-logic-with-custom-hooks.md b/src/content/learn/reusing-logic-with-custom-hooks.md
index 830b5b5fa0..7a00d8a758 100644
--- a/src/content/learn/reusing-logic-with-custom-hooks.md
+++ b/src/content/learn/reusing-logic-with-custom-hooks.md
@@ -837,6 +837,7 @@ export default function ChatRoom({ roomId }) {
### 把事件处理函数传到自定义 Hook 中 {/*passing-event-handlers-to-custom-hooks*/}
+<<<<<<< HEAD
**`useEffectEvent` API 当前仅在 React Canary 和 实验发行版中可用**。
@@ -846,6 +847,9 @@ export default function ChatRoom({ roomId }) {
当你在更多组件中使用 `useChatRoom` 时,你可能希望组件能定制它的行为。例如现在 Hook 内部收到消息的处理逻辑是硬编码:
+=======
+As you start using `useChatRoom` in more components, you might want to let components customize its behavior. For example, currently, the logic for what to do when a message arrives is hardcoded inside the Hook:
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
```js {9-11}
export function useChatRoom({ serverUrl, roomId }) {
@@ -1072,8 +1076,8 @@ export function showNotification(message, theme = 'dark') {
```json package.json hidden
{
"dependencies": {
- "react": "canary",
- "react-dom": "canary",
+ "react": "latest",
+ "react-dom": "latest",
"react-scripts": "latest",
"toastify-js": "1.12.0"
},
@@ -1718,22 +1722,6 @@ html, body { min-height: 300px; }
}
```
-```json package.json hidden
-{
- "dependencies": {
- "react": "canary",
- "react-dom": "canary",
- "react-scripts": "latest"
- },
- "scripts": {
- "start": "react-scripts start",
- "build": "react-scripts build",
- "test": "react-scripts test --env=jsdom",
- "eject": "react-scripts eject"
- }
-}
-```
-
但是 **没有必要** 这样做。和常规函数一样,最终是由你决定在哪里划分代码不同部分之间的边界。你也可以采取不一样的方法。把大部分必要的逻辑移入一个 [JavaScript 类](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes),而不是把逻辑保留在 Effect 中:
@@ -2207,22 +2195,6 @@ export function useInterval(onTick, delay) {
-```json package.json hidden
-{
- "dependencies": {
- "react": "canary",
- "react-dom": "canary",
- "react-scripts": "latest"
- },
- "scripts": {
- "start": "react-scripts start",
- "build": "react-scripts build",
- "test": "react-scripts test --env=jsdom",
- "eject": "react-scripts eject"
- }
-}
-```
-
```js
import { useCounter } from './useCounter.js';
import { useInterval } from './useInterval.js';
@@ -2278,22 +2250,6 @@ export function useInterval(onTick, delay) {
-```json package.json hidden
-{
- "dependencies": {
- "react": "canary",
- "react-dom": "canary",
- "react-scripts": "latest"
- },
- "scripts": {
- "start": "react-scripts start",
- "build": "react-scripts build",
- "test": "react-scripts test --env=jsdom",
- "eject": "react-scripts eject"
- }
-}
-```
-
```js
import { useCounter } from './useCounter.js';
diff --git a/src/content/learn/separating-events-from-effects.md b/src/content/learn/separating-events-from-effects.md
index 6d2991e4c5..1fb3f5270f 100644
--- a/src/content/learn/separating-events-from-effects.md
+++ b/src/content/learn/separating-events-from-effects.md
@@ -400,6 +400,7 @@ label { display: block; margin-top: 10px; }
### 声明一个 Effect Event {/*declaring-an-effect-event*/}
+<<<<<<< HEAD
**`useEffectEvent` API 当前仅在 React Canary 和 实验发行版中可用**。
@@ -409,6 +410,9 @@ label { display: block; margin-top: 10px; }
使用 [`useEffectEvent`](/reference/react/useEffectEvent) 这个特殊的 Hook 从 Effect 中提取非响应式逻辑:
+=======
+Use a special Hook called [`useEffectEvent`](/reference/react/useEffectEvent) to extract this non-reactive logic out of your Effect:
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
```js {1,4-6}
import { useEffect, useEffectEvent } from 'react';
@@ -450,8 +454,8 @@ function ChatRoom({ roomId, theme }) {
```json package.json hidden
{
"dependencies": {
- "react": "canary",
- "react-dom": "canary",
+ "react": "latest",
+ "react-dom": "latest",
"react-scripts": "latest",
"toastify-js": "1.12.0"
},
@@ -580,6 +584,7 @@ label { display: block; margin-top: 10px; }
### 使用 Effect Event 读取最新的 props 和 state {/*reading-latest-props-and-state-with-effect-events*/}
+<<<<<<< HEAD
**`useEffectEvent` API 当前仅在 React Canary 和 实验发行版中可用**。
@@ -589,6 +594,9 @@ label { display: block; margin-top: 10px; }
Effect Event 可以修复之前许多你可能试图抑制依赖项检查工具的地方。
+=======
+Effect Events let you fix many patterns where you might be tempted to suppress the dependency linter.
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
例如,假设你有一个记录页面访问的 Effect:
@@ -729,7 +737,11 @@ function Page({ url }) {
}
```
+<<<<<<< HEAD
等 `useEffectEvent` 成为 React 稳定部分后,我们会推荐 **永远不要抑制代码检查工具**。
+=======
+We recommend **never suppressing the linter**.
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
抑制规则的第一个缺点是当 Effect 需要对一个已经在代码中出现过的新响应式依赖项做出“响应”时,React 不会再发出警告。在稍早之前的示例中,你将 `url` 添加为依赖项,**是因为** React 提醒你去做这件事。如果禁用代码检查,你未来将不会再收到任何关于 Effect 修改的提醒。这引起了 bug。
@@ -804,22 +816,6 @@ body {
-```json package.json hidden
-{
- "dependencies": {
- "react": "canary",
- "react-dom": "canary",
- "react-scripts": "latest"
- },
- "scripts": {
- "start": "react-scripts start",
- "build": "react-scripts build",
- "test": "react-scripts test --env=jsdom",
- "eject": "react-scripts eject"
- }
-}
-```
-
```js
import { useState, useEffect } from 'react';
import { useEffectEvent } from 'react';
@@ -882,6 +878,7 @@ body {
### Effect Event 的局限性 {/*limitations-of-effect-events*/}
+<<<<<<< HEAD
**`useEffectEvent` API 当前仅在 React Canary 和 实验发行版中可用**。
@@ -891,6 +888,9 @@ body {
Effect Event 的局限性在于你如何使用他们:
+=======
+Effect Events are very limited in how you can use them:
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
* **只在 Effect 内部调用他们**。
* **永远不要把他们传给其他的组件或者 Hook**。
@@ -979,23 +979,6 @@ Effect Event 是 Effect 代码的非响应式“片段”。他们应该在使
-```json package.json hidden
-{
- "dependencies": {
- "react": "canary",
- "react-dom": "canary",
- "react-scripts": "latest"
- },
- "scripts": {
- "start": "react-scripts start",
- "build": "react-scripts build",
- "test": "react-scripts test --env=jsdom",
- "eject": "react-scripts eject"
- }
-}
-```
-
-
```js {expectedErrors: {'react-compiler': [14]}}
import { useState, useEffect } from 'react';
@@ -1049,22 +1032,6 @@ button { margin: 10px; }
-```json package.json hidden
-{
- "dependencies": {
- "react": "canary",
- "react-dom": "canary",
- "react-scripts": "latest"
- },
- "scripts": {
- "start": "react-scripts start",
- "build": "react-scripts build",
- "test": "react-scripts test --env=jsdom",
- "eject": "react-scripts eject"
- }
-}
-```
-
```js
import { useState, useEffect } from 'react';
@@ -1127,22 +1094,6 @@ button { margin: 10px; }
-```json package.json hidden
-{
- "dependencies": {
- "react": "canary",
- "react-dom": "canary",
- "react-scripts": "latest"
- },
- "scripts": {
- "start": "react-scripts start",
- "build": "react-scripts build",
- "test": "react-scripts test --env=jsdom",
- "eject": "react-scripts eject"
- }
-}
-```
-
```js
import { useState, useEffect } from 'react';
import { useEffectEvent } from 'react';
@@ -1196,22 +1147,6 @@ button { margin: 10px; }
-```json package.json hidden
-{
- "dependencies": {
- "react": "canary",
- "react-dom": "canary",
- "react-scripts": "latest"
- },
- "scripts": {
- "start": "react-scripts start",
- "build": "react-scripts build",
- "test": "react-scripts test --env=jsdom",
- "eject": "react-scripts eject"
- }
-}
-```
-
```js
import { useState, useEffect } from 'react';
import { useEffectEvent } from 'react';
@@ -1278,22 +1213,6 @@ Effect Event 内部的代码是非响应式的。哪些情况下你会 **想要*
-```json package.json hidden
-{
- "dependencies": {
- "react": "canary",
- "react-dom": "canary",
- "react-scripts": "latest"
- },
- "scripts": {
- "start": "react-scripts start",
- "build": "react-scripts build",
- "test": "react-scripts test --env=jsdom",
- "eject": "react-scripts eject"
- }
-}
-```
-
```js
import { useState, useEffect } from 'react';
import { useEffectEvent } from 'react';
@@ -1365,22 +1284,6 @@ button { margin: 10px; }
-```json package.json hidden
-{
- "dependencies": {
- "react": "canary",
- "react-dom": "canary",
- "react-scripts": "latest"
- },
- "scripts": {
- "start": "react-scripts start",
- "build": "react-scripts build",
- "test": "react-scripts test --env=jsdom",
- "eject": "react-scripts eject"
- }
-}
-```
-
```js
import { useState, useEffect } from 'react';
import { useEffectEvent } from 'react';
@@ -1464,8 +1367,8 @@ button { margin: 10px; }
```json package.json hidden
{
"dependencies": {
- "react": "canary",
- "react-dom": "canary",
+ "react": "latest",
+ "react-dom": "latest",
"react-scripts": "latest",
"toastify-js": "1.12.0"
},
@@ -1605,8 +1508,8 @@ Effect Event 伴随着两秒的延迟被调用。如果你快速地从 travel
```json package.json hidden
{
"dependencies": {
- "react": "canary",
- "react-dom": "canary",
+ "react": "latest",
+ "react-dom": "latest",
"react-scripts": "latest",
"toastify-js": "1.12.0"
},
@@ -1743,8 +1646,8 @@ label { display: block; margin-top: 10px; }
```json package.json hidden
{
"dependencies": {
- "react": "canary",
- "react-dom": "canary",
+ "react": "latest",
+ "react-dom": "latest",
"react-scripts": "latest",
"toastify-js": "1.12.0"
},
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 3edac06a48..89478c7bed 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,11 @@ React 以及许多其他 UI 库,将 UI 建模为树。将应用程序视为树
## 将 UI 视为树 {/*your-ui-as-a-tree*/}
+<<<<<<< HEAD
树是项目和 UI 之间的关系模型,通常使用树结构来表示 UI。例如,浏览器使用树结构来建模 HTML([DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model/Introduction))与CSS([CSSOM](https://developer.mozilla.org/docs/Web/API/CSS_Object_Model))。移动平台也使用树来表示其视图层次结构。
+=======
+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.
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
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 dc86831451..e8961c1765 100644
--- a/src/content/learn/you-might-not-need-an-effect.md
+++ b/src/content/learn/you-might-not-need-an-effect.md
@@ -1106,7 +1106,7 @@ input { margin-top: 10px; }
-```js {expectedErrors: {'react-compiler': [8]}}
+```js
import { useState, useMemo } from 'react';
import { initialTodos, createTodo, getVisibleTodos } from './todos.js';
diff --git a/src/content/reference/dev-tools/react-performance-tracks.md b/src/content/reference/dev-tools/react-performance-tracks.md
new file mode 100644
index 0000000000..dc2912da21
--- /dev/null
+++ b/src/content/reference/dev-tools/react-performance-tracks.md
@@ -0,0 +1,159 @@
+---
+title: React Performance tracks
+---
+
+
+
+React Performance tracks are specialized custom entries that appear on the Performance panel's timeline in your browser developer tools.
+
+
+
+These tracks are designed to provide developers with comprehensive insights into their React application's performance by visualizing React-specific events and metrics alongside other critical data sources such as network requests, JavaScript execution, and event loop activity, all synchronized on a unified timeline within the Performance panel for a complete understanding of application behavior.
+
+
+
+
+
+
+
+
+---
+
+## Usage {/*usage*/}
+
+React Performance tracks are only available in development and profiling builds of React:
+
+- **Development**: enabled by default.
+- **Profiling**: Only Scheduler tracks are enabled by default. The Components track only lists Components that are in subtrees wrapped with [``](/reference/react/Profiler). If you have [React Developer Tools extension](/learn/react-developer-tools) enabled, all Components are included in the Components track even if they're not wrapped in ``. Server tracks are not available in profiling builds.
+
+If enabled, tracks should appear automatically in the traces you record with the Performance panel of browsers that provide [extensibility APIs](https://developer.chrome.com/docs/devtools/performance/extension).
+
+
+
+The profiling instrumentation that powers React Performance tracks adds some additional overhead, so it is disabled in production builds by default.
+Server Components and Server Requests tracks are only available in development builds.
+
+
+
+### Using profiling builds {/*using-profiling-builds*/}
+
+In addition to production and development builds, React also includes a special profiling build.
+To use profiling builds, you have to use `react-dom/profiling` instead of `react-dom/client`.
+We recommend that you alias `react-dom/client` to `react-dom/profiling` at build time via bundler aliases instead of manually updating each `react-dom/client` import.
+Your framework might have built-in support for enabling React's profiling build.
+
+---
+
+## Tracks {/*tracks*/}
+
+### Scheduler {/*scheduler*/}
+
+The Scheduler is an internal React concept used for managing tasks with different priorities. This track consists of 4 subtracks, each representing work of a specific priority:
+
+- **Blocking** - The synchronous updates, which could've been initiated by user interactions.
+- **Transition** - Non-blocking work that happens in the background, usually initiated via [`startTransition`](/reference/react/startTransition).
+- **Suspense** - Work related to Suspense boundaries, such as displaying fallbacks or revealing content.
+- **Idle** - The lowest priority work that is done when there are no other tasks with higher priority.
+
+
+
+
+
+
+#### Renders {/*renders*/}
+
+Every render pass consists of multiple phases that you can see on a timeline:
+
+- **Update** - this is what caused a new render pass.
+- **Render** - React renders the updated subtree by calling render functions of components. You can see the rendered components subtree on [Components track](#components), which follows the same color scheme.
+- **Commit** - After rendering components, React will submit the changes to the DOM and run layout effects, like [`useLayoutEffect`](/reference/react/useLayoutEffect).
+- **Remaining Effects** - React runs passive effects of a rendered subtree. This usually happens after the paint, and this is when React runs hooks like [`useEffect`](/reference/react/useEffect). One known exception is user interactions, like clicks, or other discrete events. In this scenario, this phase could run before the paint.
+
+
+
+
+
+
+[Learn more about renders and commits](/learn/render-and-commit).
+
+#### Cascading updates {/*cascading-updates*/}
+
+Cascading updates is one of the patterns for performance regressions. If an update was scheduled during a render pass, React could discard completed work and start a new pass.
+
+In development builds, React can show you which Component scheduled a new update. This includes both general updates and cascading ones. You can see the enhanced stack trace by clicking on the "Cascading update" entry, which should also display the name of the method that scheduled an update.
+
+
+
+
+
+
+[Learn more about Effects](/learn/you-might-not-need-an-effect).
+
+### Components {/*components*/}
+
+The Components track visualizes the durations of React components. They are displayed as a flamegraph, where each entry represents the duration of the corresponding component render and all its descendant children components.
+
+
+
+
+
+
+Similar to render durations, effect durations are also represented as a flamegraph, but with a different color scheme that aligns with the corresponding phase on the Scheduler track.
+
+
+
+
+
+
+
+
+Unlike renders, not all effects are shown on the Components track by default.
+
+To maintain performance and prevent UI clutter, React will only display those effects, which had a duration of 0.05ms or longer, or triggered an update.
+
+
+
+Additional events may be displayed during the render and effects phases:
+
+- Mount - A corresponding subtree of component renders or effects was mounted.
+- Unmount - A corresponding subtree of component renders or effects was unmounted.
+- Reconnect - Similar to Mount, but limited to cases when [``](/reference/react/Activity) is used.
+- Disconnect - Similar to Unmount, but limited to cases when [``](/reference/react/Activity) is used.
+
+#### Changed props {/*changed-props*/}
+
+In development builds, when you click on a component render entry, you can inspect potential changes in props. You can use this information to identify unnecessary renders.
+
+
+
+
+
+
+### Server {/*server*/}
+
+
+
+
+
+
+#### Server Requests {/*server-requests*/}
+
+The Server Requests track visualized all Promises that eventually end up in a React Server Component. This includes any `async` operations like calling `fetch` or async Node.js file operations.
+
+React will try to combine Promises that are started from inside third-party code into a single span representing the the duration of the entire operation blocking 1st party code.
+For example, a third party library method called `getUser` that calls `fetch` internally multiple times will be represented as a single span called `getUser`, instead of showing multiple `fetch` spans.
+
+Clicking on spans will show you a stack trace of where the Promise was created as well as a view of the value that the Promise resolved to, if available.
+
+Rejected Promises are displayed as red with their rejected value.
+
+#### Server Components {/*server-components*/}
+
+The Server Components tracks visualize the durations of React Server Components Promises they awaited. Timings are displayed as a flamegraph, where each entry represents the duration of the corresponding component render and all its descendant children components.
+
+If you await a Promise, React will display duration of that Promise. To see all I/O operations, use the Server Requests track.
+
+Different colors are used to indicate the duration of the component render. The darker the color, the longer the duration.
+
+The Server Components track group will always contain a "Primary" track. If React is able to render Server Components concurrently, it will display addititional "Parallel" tracks.
+If more than 8 Server Components are rendered concurrently, React will associate them with the last "Parallel" track instead of adding more tracks.
diff --git a/src/content/reference/eslint-plugin-react-hooks/index.md b/src/content/reference/eslint-plugin-react-hooks/index.md
index 21e1222d80..b3a16bc370 100644
--- a/src/content/reference/eslint-plugin-react-hooks/index.md
+++ b/src/content/reference/eslint-plugin-react-hooks/index.md
@@ -9,14 +9,6 @@ version: rc
-
-
-These docs include rules available in the RC version of `eslint-plugin-react-hooks`.
-
-You can try them by upgrading the lint plugin [to the most recent RC version](/learn/react-compiler/installation#eslint-integration).
-
-
-
This plugin helps you catch violations of React's rules at build time, ensuring your components and hooks follow React's rules for correctness and performance. The lints cover both fundamental React patterns (exhaustive-deps and rules-of-hooks) and issues flagged by React Compiler. React Compiler diagnostics are automatically surfaced by this ESLint plugin, and can be used even if your app hasn't adopted the compiler yet.
@@ -25,15 +17,12 @@ When the compiler reports a diagnostic, it means that the compiler was able to s
What this means for linting, is that you don’t need to fix all violations immediately. Address them at your own pace to gradually increase the number of optimized components.
-## Available Lints {/*available-lints*/}
+## Recommended Rules {/*recommended*/}
-These rules are available in the stable version of `eslint-plugin-react-hooks`:
+These rules are included in the `recommended` preset in `eslint-plugin-react-hooks`:
* [`exhaustive-deps`](/reference/eslint-plugin-react-hooks/lints/exhaustive-deps) - Validates that dependency arrays for React hooks contain all necessary dependencies
* [`rules-of-hooks`](/reference/eslint-plugin-react-hooks/lints/rules-of-hooks) - Validates that components and hooks follow the Rules of Hooks
-
-These rules are available in the RC version of `eslint-plugin-react-hooks`:
-
* [`component-hook-factories`](/reference/eslint-plugin-react-hooks/lints/component-hook-factories) - Validates higher order functions defining nested components or hooks
* [`config`](/reference/eslint-plugin-react-hooks/lints/config) - Validates the compiler configuration options
* [`error-boundaries`](/reference/eslint-plugin-react-hooks/lints/error-boundaries) - Validates usage of Error Boundaries instead of try/catch for child errors
diff --git a/src/content/reference/eslint-plugin-react-hooks/lints/component-hook-factories.md b/src/content/reference/eslint-plugin-react-hooks/lints/component-hook-factories.md
index 44d23d758f..537903abdd 100644
--- a/src/content/reference/eslint-plugin-react-hooks/lints/component-hook-factories.md
+++ b/src/content/reference/eslint-plugin-react-hooks/lints/component-hook-factories.md
@@ -1,6 +1,5 @@
---
title: component-hook-factories
-version: rc
---
@@ -9,14 +8,6 @@ Validates against higher order functions defining nested components or hooks. Co
-
-
-This rule is available in the RC version of `eslint-plugin-react-hooks`.
-
-You can try it by upgrading the lint plugin [to the most recent RC version](/learn/react-compiler/installation#eslint-integration).
-
-
-
## Rule Details {/*rule-details*/}
Defining components or hooks inside other functions creates new instances on every call. React treats each as a completely different component, destroying and recreating the entire component tree, losing all state, and causing performance problems.
diff --git a/src/content/reference/eslint-plugin-react-hooks/lints/config.md b/src/content/reference/eslint-plugin-react-hooks/lints/config.md
index f7e099752b..719e08412e 100644
--- a/src/content/reference/eslint-plugin-react-hooks/lints/config.md
+++ b/src/content/reference/eslint-plugin-react-hooks/lints/config.md
@@ -1,6 +1,5 @@
---
title: config
-version: rc
---
@@ -9,14 +8,6 @@ Validates the compiler [configuration options](/reference/react-compiler/configu
-
-
-This rule is available in the RC version of `eslint-plugin-react-hooks`.
-
-You can try it by upgrading the lint plugin [to the most recent RC version](/learn/react-compiler/installation#eslint-integration).
-
-
-
## Rule Details {/*rule-details*/}
React Compiler accepts various [configuration options](/reference/react-compiler/configuration) to control its behavior. This rule validates that your configuration uses correct option names and value types, preventing silent failures from typos or incorrect settings.
diff --git a/src/content/reference/eslint-plugin-react-hooks/lints/error-boundaries.md b/src/content/reference/eslint-plugin-react-hooks/lints/error-boundaries.md
index bd013f5325..830098e5be 100644
--- a/src/content/reference/eslint-plugin-react-hooks/lints/error-boundaries.md
+++ b/src/content/reference/eslint-plugin-react-hooks/lints/error-boundaries.md
@@ -1,6 +1,5 @@
---
title: error-boundaries
-version: rc
---
@@ -9,14 +8,6 @@ Validates usage of Error Boundaries instead of try/catch for errors in child com
-
-
-This rule is available in the RC version of `eslint-plugin-react-hooks`.
-
-You can try it by upgrading the lint plugin [to the most recent RC version](/learn/react-compiler/installation#eslint-integration).
-
-
-
## Rule Details {/*rule-details*/}
Try/catch blocks can't catch errors that happen during React's rendering process. Errors thrown in rendering methods or hooks bubble up through the component tree. Only [Error Boundaries](/reference/react/Component#catching-rendering-errors-with-an-error-boundary) can catch these errors.
diff --git a/src/content/reference/eslint-plugin-react-hooks/lints/exhaustive-deps.md b/src/content/reference/eslint-plugin-react-hooks/lints/exhaustive-deps.md
index cd26483a14..daa7db6a81 100644
--- a/src/content/reference/eslint-plugin-react-hooks/lints/exhaustive-deps.md
+++ b/src/content/reference/eslint-plugin-react-hooks/lints/exhaustive-deps.md
@@ -140,7 +140,21 @@ useEffect(() => {
## Options {/*options*/}
-This rule accepts an options object:
+You can configure custom effect hooks using shared ESLint settings (available in `eslint-plugin-react-hooks` 6.1.1 and later):
+
+```js
+{
+ "settings": {
+ "react-hooks": {
+ "additionalEffectHooks": "(useMyEffect|useCustomEffect)"
+ }
+ }
+}
+```
+
+- `additionalEffectHooks`: Regex pattern matching custom hooks that should be checked for exhaustive dependencies. This configuration is shared across all `react-hooks` rules.
+
+For backward compatibility, this rule also accepts a rule-level option:
```js
{
@@ -152,4 +166,4 @@ This rule accepts an options object:
}
```
-- `additionalHooks`: Regex for hooks that should be checked for exhaustive dependencies
+- `additionalHooks`: Regex for hooks that should be checked for exhaustive dependencies. **Note:** If this rule-level option is specified, it takes precedence over the shared `settings` configuration.
diff --git a/src/content/reference/eslint-plugin-react-hooks/lints/gating.md b/src/content/reference/eslint-plugin-react-hooks/lints/gating.md
index fdbbadf0ef..3bd662a86e 100644
--- a/src/content/reference/eslint-plugin-react-hooks/lints/gating.md
+++ b/src/content/reference/eslint-plugin-react-hooks/lints/gating.md
@@ -1,6 +1,5 @@
---
title: gating
-version: rc
---
@@ -9,14 +8,6 @@ Validates configuration of [gating mode](/reference/react-compiler/gating).
-
-
-This rule is available in the RC version of `eslint-plugin-react-hooks`.
-
-You can try it by upgrading the lint plugin [to the most recent RC version](/learn/react-compiler/installation#eslint-integration).
-
-
-
## Rule Details {/*rule-details*/}
Gating mode lets you gradually adopt React Compiler by marking specific components for optimization. This rule ensures your gating configuration is valid so the compiler knows which components to process.
diff --git a/src/content/reference/eslint-plugin-react-hooks/lints/globals.md b/src/content/reference/eslint-plugin-react-hooks/lints/globals.md
index b9a20d4dbc..fe0cbe0080 100644
--- a/src/content/reference/eslint-plugin-react-hooks/lints/globals.md
+++ b/src/content/reference/eslint-plugin-react-hooks/lints/globals.md
@@ -1,6 +1,5 @@
---
title: globals
-version: rc
---
@@ -9,14 +8,6 @@ Validates against assignment/mutation of globals during render, part of ensuring
-
-
-This rule is available in the RC version of `eslint-plugin-react-hooks`.
-
-You can try it by upgrading the lint plugin [to the most recent RC version](/learn/react-compiler/installation#eslint-integration).
-
-
-
## Rule Details {/*rule-details*/}
Global variables exist outside React's control. When you modify them during render, you break React's assumption that rendering is pure. This can cause components to behave differently in development vs production, break Fast Refresh, and make your app impossible to optimize with features like React Compiler.
diff --git a/src/content/reference/eslint-plugin-react-hooks/lints/immutability.md b/src/content/reference/eslint-plugin-react-hooks/lints/immutability.md
index 9376271ebd..2314cde064 100644
--- a/src/content/reference/eslint-plugin-react-hooks/lints/immutability.md
+++ b/src/content/reference/eslint-plugin-react-hooks/lints/immutability.md
@@ -1,6 +1,5 @@
---
title: immutability
-version: rc
---
@@ -9,14 +8,6 @@ Validates against mutating props, state, and other values that [are immutable](/
-
-
-This rule is available in the RC version of `eslint-plugin-react-hooks`.
-
-You can try it by upgrading the lint plugin [to the most recent RC version](/learn/react-compiler/installation#eslint-integration).
-
-
-
## Rule Details {/*rule-details*/}
A component’s props and state are immutable snapshots. Never mutate them directly. Instead, pass new props down, and use the setter function from `useState`.
diff --git a/src/content/reference/eslint-plugin-react-hooks/lints/incompatible-library.md b/src/content/reference/eslint-plugin-react-hooks/lints/incompatible-library.md
index aa58775032..e057e1978d 100644
--- a/src/content/reference/eslint-plugin-react-hooks/lints/incompatible-library.md
+++ b/src/content/reference/eslint-plugin-react-hooks/lints/incompatible-library.md
@@ -1,6 +1,5 @@
---
title: incompatible-library
-version: rc
---
@@ -9,14 +8,6 @@ Validates against usage of libraries which are incompatible with memoization (ma
-
-
-This rule is available in the RC version of `eslint-plugin-react-hooks`.
-
-You can try it by upgrading the lint plugin [to the most recent RC version](/learn/react-compiler/installation#eslint-integration).
-
-
-
These libraries were designed before React's memoization rules were fully documented. They made the correct choices at the time to optimize for ergonomic ways to keep components just the right amount of reactive as app state changes. While these legacy patterns worked, we have since discovered that it's incompatible with React's programming model. We will continue working with library authors to migrate these libraries to use patterns that follow the Rules of React.
diff --git a/src/content/reference/eslint-plugin-react-hooks/lints/preserve-manual-memoization.md b/src/content/reference/eslint-plugin-react-hooks/lints/preserve-manual-memoization.md
index 2f296ac56b..93b582b1e1 100644
--- a/src/content/reference/eslint-plugin-react-hooks/lints/preserve-manual-memoization.md
+++ b/src/content/reference/eslint-plugin-react-hooks/lints/preserve-manual-memoization.md
@@ -1,6 +1,5 @@
---
title: preserve-manual-memoization
-version: rc
---
@@ -9,14 +8,6 @@ Validates that existing manual memoization is preserved by the compiler. React C
-
-
-This rule is available in the RC version of `eslint-plugin-react-hooks`.
-
-You can try it by upgrading the lint plugin [to the most recent RC version](/learn/react-compiler/installation#eslint-integration).
-
-
-
## Rule Details {/*rule-details*/}
React Compiler preserves your existing `useMemo`, `useCallback`, and `React.memo` calls. If you've manually memoized something, the compiler assumes you had a good reason and won't remove it. However, incomplete dependencies prevent the compiler from understanding your code's data flow and applying further optimizations.
diff --git a/src/content/reference/eslint-plugin-react-hooks/lints/purity.md b/src/content/reference/eslint-plugin-react-hooks/lints/purity.md
index 14c870fb53..af8aacc612 100644
--- a/src/content/reference/eslint-plugin-react-hooks/lints/purity.md
+++ b/src/content/reference/eslint-plugin-react-hooks/lints/purity.md
@@ -1,6 +1,5 @@
---
title: purity
-version: rc
---
@@ -9,14 +8,6 @@ Validates that [components/hooks are pure](/reference/rules/components-and-hooks
-
-
-This rule is available in the RC version of `eslint-plugin-react-hooks`.
-
-You can try it by upgrading the lint plugin [to the most recent RC version](/learn/react-compiler/installation#eslint-integration).
-
-
-
## Rule Details {/*rule-details*/}
React components must be pure functions - given the same props, they should always return the same JSX. When components use functions like `Math.random()` or `Date.now()` during render, they produce different output each time, breaking React's assumptions and causing bugs like hydration mismatches, incorrect memoization, and unpredictable behavior.
diff --git a/src/content/reference/eslint-plugin-react-hooks/lints/refs.md b/src/content/reference/eslint-plugin-react-hooks/lints/refs.md
index 78776ba572..3108fdd89d 100644
--- a/src/content/reference/eslint-plugin-react-hooks/lints/refs.md
+++ b/src/content/reference/eslint-plugin-react-hooks/lints/refs.md
@@ -1,6 +1,5 @@
---
title: refs
-version: rc
---
@@ -9,14 +8,6 @@ Validates correct usage of refs, not reading/writing during render. See the "pit
-
-
-This rule is available in the RC version of `eslint-plugin-react-hooks`.
-
-You can try it by upgrading the lint plugin [to the most recent RC version](/learn/react-compiler/installation#eslint-integration).
-
-
-
## Rule Details {/*rule-details*/}
Refs hold values that aren't used for rendering. Unlike state, changing a ref doesn't trigger a re-render. Reading or writing `ref.current` during render breaks React's expectations. Refs might not be initialized when you try to read them, and their values can be stale or inconsistent.
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 6508fc867f..56a9d74beb 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
@@ -159,3 +159,21 @@ const [permissions, setPermissions] = useState(
userType === 'admin' ? adminPerms : userPerms
);
```
+
+## Options {/*options*/}
+
+You can configure custom effect hooks using shared ESLint settings (available in `eslint-plugin-react-hooks` 6.1.1 and later):
+
+```js
+{
+ "settings": {
+ "react-hooks": {
+ "additionalEffectHooks": "(useMyEffect|useCustomEffect)"
+ }
+ }
+}
+```
+
+- `additionalEffectHooks`: Regex pattern matching custom hooks that should be treated as effects. This allows `useEffectEvent` and similar event functions to be called from your custom effect hooks.
+
+This shared configuration is used by both `rules-of-hooks` and `exhaustive-deps` rules, ensuring consistent behavior across all hook-related linting.
diff --git a/src/content/reference/eslint-plugin-react-hooks/lints/set-state-in-effect.md b/src/content/reference/eslint-plugin-react-hooks/lints/set-state-in-effect.md
index df285fedfe..64fa5c655a 100644
--- a/src/content/reference/eslint-plugin-react-hooks/lints/set-state-in-effect.md
+++ b/src/content/reference/eslint-plugin-react-hooks/lints/set-state-in-effect.md
@@ -1,6 +1,5 @@
---
title: set-state-in-effect
-version: rc
---
@@ -9,14 +8,6 @@ Validates against calling setState synchronously in an effect, which can lead to
-
-
-This rule is available in the RC version of `eslint-plugin-react-hooks`.
-
-You can try it by upgrading the lint plugin [to the most recent RC version](/learn/react-compiler/installation#eslint-integration).
-
-
-
## Rule Details {/*rule-details*/}
Setting state immediately inside an effect forces React to restart the entire render cycle. When you update state in an effect, React must re-render your component, apply changes to the DOM, and then run effects again. This creates an extra render pass that could have been avoided by transforming data directly during render or deriving state from props. Transform data at the top level of your component instead. This code will naturally re-run when props or state change without triggering additional render cycles.
@@ -80,7 +71,7 @@ function Component({selectedId, items}) {
Examples of correct code for this rule:
-```js {expectedErrors: {'react-compiler': [8]}}
+```js
// ✅ setState in an effect is fine if the value comes from a ref
function Tooltip() {
const ref = useRef(null);
diff --git a/src/content/reference/eslint-plugin-react-hooks/lints/set-state-in-render.md b/src/content/reference/eslint-plugin-react-hooks/lints/set-state-in-render.md
index c8cfa22a02..7517d5f928 100644
--- a/src/content/reference/eslint-plugin-react-hooks/lints/set-state-in-render.md
+++ b/src/content/reference/eslint-plugin-react-hooks/lints/set-state-in-render.md
@@ -1,32 +1,23 @@
---
title: set-state-in-render
-version: rc
---
-Validates against setting state during render, which can trigger additional renders and potential infinite render loops.
+Validates against unconditionally setting state during render, which can trigger additional renders and potential infinite render loops.
-
-
-This rule is available in the RC version of `eslint-plugin-react-hooks`.
-
-You can try it by upgrading the lint plugin [to the most recent RC version](/learn/react-compiler/installation#eslint-integration).
-
-
-
## Rule Details {/*rule-details*/}
-Calling `setState` during render triggers another render before the current one finishes. This creates an infinite loop that crashes your app.
+Calling `setState` during render unconditionally triggers another render before the current one finishes. This creates an infinite loop that crashes your app.
## Common Violations {/*common-violations*/}
### Invalid {/*invalid*/}
```js {expectedErrors: {'react-compiler': [4]}}
-// ❌ setState directly in render
+// ❌ Unconditional setState directly in render
function Component({value}) {
const [count, setCount] = useState(0);
setCount(value); // Infinite loop!
@@ -59,6 +50,19 @@ function Component({user}) {
const email = user?.email || '';
return
{name}
;
}
+
+// ✅ Conditionally derive state from props and state from previous renders
+function Component({ items }) {
+ const [isReverse, setIsReverse] = useState(false);
+ const [selection, setSelection] = useState(null);
+
+ const [prevItems, setPrevItems] = useState(items);
+ if (items !== prevItems) { // This condition makes it valid
+ setPrevItems(items);
+ setSelection(null);
+ }
+ // ...
+}
```
## Troubleshooting {/*troubleshooting*/}
@@ -102,3 +106,5 @@ function Counter({max}) {
```
Now the setter only runs in response to the click, React finishes the render normally, and `count` never crosses `max`.
+
+In rare cases, you may need to adjust state based on information from previous renders. For those, follow [this pattern](https://react.dev/reference/react/useState#storing-information-from-previous-renders) of setting state conditionally.
diff --git a/src/content/reference/eslint-plugin-react-hooks/lints/static-components.md b/src/content/reference/eslint-plugin-react-hooks/lints/static-components.md
index 06945838f3..bd52f07037 100644
--- a/src/content/reference/eslint-plugin-react-hooks/lints/static-components.md
+++ b/src/content/reference/eslint-plugin-react-hooks/lints/static-components.md
@@ -1,6 +1,5 @@
---
title: static-components
-version: rc
---
@@ -9,14 +8,6 @@ Validates that components are static, not recreated every render. Components tha
-
-
-This rule is available in the RC version of `eslint-plugin-react-hooks`.
-
-You can try it by upgrading the lint plugin [to the most recent RC version](/learn/react-compiler/installation#eslint-integration).
-
-
-
## Rule Details {/*rule-details*/}
Components defined inside other components are recreated on every render. React sees each as a brand new component type, unmounting the old one and mounting the new one, destroying all state and DOM nodes in the process.
@@ -38,10 +29,10 @@ function Parent() {
// ❌ Dynamic component creation
function Parent({type}) {
- const Component = type === 'button'
+ const Component = type === 'button'
? () =>
: () =>
;
function Parent({type}) {
- const Component = type === 'button'
+ const Component = type === 'button'
? ButtonComponent // Reference existing component
: TextComponent;
-
+
return ;
}
```
@@ -74,7 +65,7 @@ You might define components inside to access local state:
// ❌ Wrong: Inner component to access parent state
function Parent() {
const [theme, setTheme] = useState('light');
-
+
function ThemedButton() { // Recreated every render!
return (
);
}
-
+
return ;
}
```
diff --git a/src/content/reference/eslint-plugin-react-hooks/lints/unsupported-syntax.md b/src/content/reference/eslint-plugin-react-hooks/lints/unsupported-syntax.md
index 3f3e04d53a..a3eefcdb24 100644
--- a/src/content/reference/eslint-plugin-react-hooks/lints/unsupported-syntax.md
+++ b/src/content/reference/eslint-plugin-react-hooks/lints/unsupported-syntax.md
@@ -1,6 +1,5 @@
---
title: unsupported-syntax
-version: rc
---
@@ -9,14 +8,6 @@ Validates against syntax that React Compiler does not support. If you need to, y
-
-
-This rule is available in the RC version of `eslint-plugin-react-hooks`.
-
-You can try it by upgrading the lint plugin [to the most recent RC version](/learn/react-compiler/installation#eslint-integration).
-
-
-
## Rule Details {/*rule-details*/}
React Compiler needs to statically analyze your code to apply optimizations. Features like `eval` and `with` make it impossible to statically understand what the code does at compile time, so the compiler can't optimize components that use them.
diff --git a/src/content/reference/eslint-plugin-react-hooks/lints/use-memo.md b/src/content/reference/eslint-plugin-react-hooks/lints/use-memo.md
index db022a802f..a5a77e5f6e 100644
--- a/src/content/reference/eslint-plugin-react-hooks/lints/use-memo.md
+++ b/src/content/reference/eslint-plugin-react-hooks/lints/use-memo.md
@@ -1,22 +1,13 @@
---
title: use-memo
-version: rc
---
-Validates usage of the `useMemo` hook without a return value. See [`useMemo` docs](/reference/react/useMemo) for more information.
+Validates that the `useMemo` hook is used with a return value. See [`useMemo` docs](/reference/react/useMemo) for more information.
-
-
-This rule is available in the RC version of `eslint-plugin-react-hooks`.
-
-You can try it by upgrading the lint plugin [to the most recent RC version](/learn/react-compiler/installation#eslint-integration).
-
-
-
## Rule Details {/*rule-details*/}
`useMemo` is for computing and caching expensive values, not for side effects. Without a return value, `useMemo` returns `undefined`, which defeats its purpose and likely indicates you're using the wrong hook.
diff --git a/src/content/reference/react-compiler/compiling-libraries.md b/src/content/reference/react-compiler/compiling-libraries.md
index f09ffcb725..ec0a7581ea 100644
--- a/src/content/reference/react-compiler/compiling-libraries.md
+++ b/src/content/reference/react-compiler/compiling-libraries.md
@@ -21,7 +21,7 @@ As a library author, you can compile your library code before publishing to npm.
Add React Compiler to your library's build process:
-npm install -D babel-plugin-react-compiler@rc
+npm install -D babel-plugin-react-compiler@latest
Configure your build tool to compile your library. For example, with Babel:
@@ -45,13 +45,13 @@ If your library supports React versions below 19, you'll need additional configu
We recommend installing react-compiler-runtime as a direct dependency:
-npm install react-compiler-runtime@rc
+npm install react-compiler-runtime@latest
```json
{
"dependencies": {
- "react-compiler-runtime": "^19.1.0-rc.2"
+ "react-compiler-runtime": "^1.0.0"
},
"peerDependencies": {
"react": "^17.0.0 || ^18.0.0 || ^19.0.0"
diff --git a/src/content/reference/react-compiler/configuration.md b/src/content/reference/react-compiler/configuration.md
index c240d8f4cc..144e9a16f1 100644
--- a/src/content/reference/react-compiler/configuration.md
+++ b/src/content/reference/react-compiler/configuration.md
@@ -130,7 +130,7 @@ module.exports = {
较旧的 React 版本需要安装运行环境包并设置 target:
```bash
-npm install react-compiler-runtime@rc
+npm install react-compiler-runtime@latest
```
```js
diff --git a/src/content/reference/react-compiler/target.md b/src/content/reference/react-compiler/target.md
index ef9523f6fd..1bdb4f6508 100644
--- a/src/content/reference/react-compiler/target.md
+++ b/src/content/reference/react-compiler/target.md
@@ -40,7 +40,16 @@ title: target
- **`'18'`**: 以 React 18 为目标。需要安装 `react-compiler-runtime` 包。
- **`'17'`**: 以 React 17 为目标。需要安装 `react-compiler-runtime` 包。
+<<<<<<< HEAD
#### 注意事项 {/*caveats*/}
+=======
+#### Caveats {/*caveats*/}
+
+- Always use string values, not numbers (e.g., `'17'` not `17`)
+- Don't include patch versions (e.g., use `'18'` not `'18.2.0'`)
+- React 19 includes built-in compiler runtime APIs
+- React 17 and 18 require installing `react-compiler-runtime@latest`
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
- 始终使用字符串值,不要用数字(例如使用 `'17'` 而非 `17`)
- 不要包含补丁版本号(例如使用 `'18'` 而非 `'18.2.0'`)
@@ -75,7 +84,7 @@ import { c as _c } from 'react/compiler-runtime';
1. 安装运行环境包:
```bash
-npm install react-compiler-runtime@rc
+npm install react-compiler-runtime@latest
```
2. 配置 target:
@@ -114,7 +123,7 @@ import { c as _c } from 'react-compiler-runtime';
2. 如果使用 React 17 或 18,安装运行环境:
```bash
- npm install react-compiler-runtime@rc
+ npm install react-compiler-runtime@latest
```
3. 确保你的 target 和你的 React 版本一致:
@@ -128,10 +137,17 @@ import { c as _c } from 'react-compiler-runtime';
请确保运行环境包:
+<<<<<<< HEAD
1. 安装在你的项目中(而非全局)
2. 被列在 `package.json` 的 dependencies 中
3. 使用正确版本(`@rc` 标签)
4. 不在 `devDependencies` 中(运行环境需要)
+=======
+1. Installed in your project (not globally)
+2. Listed in your `package.json` dependencies
+3. The correct version (`@latest` tag)
+4. Not in `devDependencies` (it's needed at runtime)
+>>>>>>> 9ef1c4741776a14b034711cc03e4124ccc53e337
### 检查编译输出 {/*checking-output*/}
diff --git a/src/content/reference/react-dom/components/form.md b/src/content/reference/react-dom/components/form.md
index b17b1a40b0..1043b13a0d 100644
--- a/src/content/reference/react-dom/components/form.md
+++ b/src/content/reference/react-dom/components/form.md
@@ -278,7 +278,7 @@ export default function Search() {
Displaying a form submission error message before the JavaScript bundle loads for progressive enhancement requires that:
-1. `