Skip to content

Commit 1b18c88

Browse files
Merge branch 'main' of https://github.com/reactjs/react.dev into sync-9467bc58
2 parents 945bdfc + 9467bc5 commit 1b18c88

File tree

5 files changed

+79
-106
lines changed

5 files changed

+79
-106
lines changed

src/content/learn/react-compiler.md

Lines changed: 64 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ title: React Compiler
33
---
44

55
<Intro>
6-
This page will give you an introduction to the new experimental React Compiler and how to try it out successfully.
6+
This page will give you an introduction to React Compiler and how to try it out successfully.
77
</Intro>
88

99
<Wip>
@@ -19,14 +19,28 @@ These docs are still a work in progress. More documentation is available in the
1919
</YouWillLearn>
2020

2121
<Note>
22-
React Compiler is a new experimental compiler that we've open sourced to get early feedback from the community. It still has rough edges and is not yet fully ready for production.
22+
React Compiler is a new compiler currently in Beta, that we've open sourced to get early feedback from the community. 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).
2323

24-
React Compiler requires React 19 RC. If you are unable to upgrade to React 19, you may try a userspace implementation of the cache function as described in the [Working Group](https://github.com/reactwg/react-compiler/discussions/6). However, please note that this is not recommended and you should upgrade to React 19 when possible.
24+
The latest Beta release can be found with the `@beta` tag, and daily experimental releases with `@experimental`.
2525
</Note>
2626

27-
React Compiler is a new experimental compiler that we've open sourced to get early feedback from the community. It is a build-time only tool that automatically optimizes your React app. It works with plain JavaScript, and understands the [Rules of React](/reference/rules), so you don't need to rewrite any code to use it.
27+
React Compiler is a new compiler that we've open sourced to get early feedback from the community. It is a build-time only tool that automatically optimizes your React app. It works with plain JavaScript, and understands the [Rules of React](/reference/rules), so you don't need to rewrite any code to use it.
2828

29-
The compiler also includes an [eslint plugin](#installing-eslint-plugin-react-compiler) that surfaces the analysis from the compiler right in your editor. The plugin runs independently of the compiler and can be used even if you aren't using the compiler in your app. We recommend all React developers to use this eslint plugin to help improve the quality of your codebase.
29+
The compiler also includes an [eslint plugin](#installing-eslint-plugin-react-compiler) that surfaces the analysis from the compiler right in your editor. **We strongly recommend everyone use the linter today.** The linter does not require that you have the compiler installed, so you can use it even if you are not ready to try out the compiler.
30+
31+
The compiler is currently released as `beta`, and is available to try out on React 17+ apps and libraries. To install the Beta:
32+
33+
<TerminalBlock>
34+
npm install -D babel-plugin-react-compiler@beta eslint-plugin-react-compiler@beta
35+
</TerminalBlock>
36+
37+
Or, if you're using Yarn:
38+
39+
<TerminalBlock>
40+
yarn add -D babel-plugin-react-compiler@beta eslint-plugin-react-compiler@beta
41+
</TerminalBlock>
42+
43+
If you are not using React 19 yet, please see [the section below](#using-react-compiler-with-react-17-or-18) for further instructions.
3044

3145
### What does the compiler do? {/*what-does-the-compiler-do*/}
3246

@@ -96,19 +110,9 @@ However, if `expensivelyProcessAReallyLargeArrayOfObjects` is truly an expensive
96110
So if `expensivelyProcessAReallyLargeArrayOfObjects` was used in many different components, even if the same exact items were passed down, that expensive calculation would be run repeatedly. We recommend [profiling](https://react.dev/reference/react/useMemo#how-to-tell-if-a-calculation-is-expensive) first to see if it really is that expensive before making code more complicated.
97111
</DeepDive>
98112

99-
### What does the compiler assume? {/*what-does-the-compiler-assume*/}
100-
101-
React Compiler assumes that your code:
102-
103-
1. Is valid, semantic JavaScript
104-
2. Tests that nullable/optional values and properties are defined before accessing them (for example, by enabling [`strictNullChecks`](https://www.typescriptlang.org/tsconfig/#strictNullChecks) if using TypeScript), i.e., `if (object.nullableProperty) { object.nullableProperty.foo }` or with optional-chaining `object.nullableProperty?.foo`
105-
3. Follows the [Rules of React](https://react.dev/reference/rules)
106-
107-
React Compiler can verify many of the Rules of React statically, and will safely skip compilation when it detects an error. To see the errors we recommend also installing [eslint-plugin-react-compiler](https://www.npmjs.com/package/eslint-plugin-react-compiler).
108-
109113
### Should I try out the compiler? {/*should-i-try-out-the-compiler*/}
110114

111-
Please note that the compiler is still experimental and has many rough edges. 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).
115+
Please note that the compiler is still in Beta and has many rough edges. 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).
112116

113117
**You don't have to rush into using the compiler now. It's okay to wait until it reaches a stable release before adopting it.** However, we do appreciate trying it out in small experiments in your apps so that you can [provide feedback](#reporting-issues) to us to help make the compiler better.
114118

@@ -121,7 +125,7 @@ In addition to these docs, we recommend checking the [React Compiler Working Gro
121125
Prior to installing the compiler, you can first check to see if your codebase is compatible:
122126

123127
<TerminalBlock>
124-
npx react-compiler-healthcheck@experimental
128+
npx react-compiler-healthcheck@beta
125129
</TerminalBlock>
126130

127131
This script will:
@@ -143,7 +147,7 @@ Found no usage of incompatible libraries.
143147
React Compiler also powers an eslint plugin. The eslint plugin can be used **independently** of the compiler, meaning you can use the eslint plugin even if you don't use the compiler.
144148

145149
<TerminalBlock>
146-
npm install eslint-plugin-react-compiler@experimental
150+
npm install -D eslint-plugin-react-compiler@beta
147151
</TerminalBlock>
148152

149153
Then, add it to your eslint config:
@@ -178,32 +182,53 @@ const ReactCompilerConfig = {
178182
};
179183
```
180184

181-
In rare cases, you can also configure the compiler to run in "opt-in" mode using the `compilationMode: "annotation"` option. This makes it so the compiler will only compile components and hooks annotated with a `"use memo"` directive. Please note that the `annotation` mode is a temporary one to aid early adopters, and that we don't intend for the `"use memo"` directive to be used for the long term.
185+
When you have more confidence with rolling out the compiler, you can expand coverage to other directories as well and slowly roll it out to your whole app.
186+
187+
#### New projects {/*new-projects*/}
182188

183-
```js {2,7}
189+
If you're starting a new project, you can enable the compiler on your entire codebase, which is the default behavior.
190+
191+
### Using React Compiler with React 17 or 18 {/*using-react-compiler-with-react-17-or-18*/}
192+
193+
React Compiler works best with React 19 RC. If you are unable to upgrade, you can install the extra `react-compiler-runtime` package which will allow the compiled code to run on versions prior to 19. However, note that the minimum supported version is 17.
194+
195+
<TerminalBlock>
196+
npm install react-compiler-runtime@beta
197+
</TerminalBlock>
198+
199+
You should also add the correct `target` to your compiler config, where `target` is the major version of React you are targeting:
200+
201+
```js {3}
202+
// babel.config.js
184203
const ReactCompilerConfig = {
185-
compilationMode: "annotation",
204+
target: '18' // '17' | '18' | '19'
186205
};
187206

188-
// src/app.jsx
189-
export default function App() {
190-
"use memo";
191-
// ...
192-
}
207+
module.exports = function () {
208+
return {
209+
plugins: [
210+
['babel-plugin-react-compiler', ReactCompilerConfig],
211+
],
212+
};
213+
};
193214
```
194215

195-
When you have more confidence with rolling out the compiler, you can expand coverage to other directories as well and slowly roll it out to your whole app.
216+
### Using the compiler on libraries {/*using-the-compiler-on-libraries*/}
196217

197-
#### New projects {/*new-projects*/}
218+
React Compiler can also be used to compile libraries. Because React Compiler needs to run on the original source code prior to any code transformations, it is not possible for an application's build pipeline to compile the libraries they use. Hence, our recommendation is for library maintainers to independently compile and test their libraries with the compiler, and ship compiled code to npm.
198219

199-
If you're starting a new project, you can enable the compiler on your entire codebase, which is the default behavior.
220+
Because your code is pre-compiled, users of your library will not need to have the compiler enabled in order to benefit from the automatic memoization applied to your library. If your library targets apps not yet on React 19, specify a minimum [`target` and add `react-compiler-runtime` as a direct dependency](#using-react-compiler-with-react-17-or-18). The runtime package will use the correct implementation of APIs depending on the application's version, and polyfill the missing APIs if necessary.
221+
222+
Library code can often require more complex patterns and usage of escape hatches. For this reason, we recommend ensuring that you have sufficient testing in order to identify any issues that might arise from using the compiler on your library. If you identify any issues, you can always opt-out the specific components or hooks with the [`'use no memo'` directive](#something-is-not-working-after-compilation).
223+
224+
Similarly to apps, it is not necessary to fully compile 100% of your components or hooks to see benefits in your library. A good starting point might be to identify the most performance sensitive parts of your library and ensuring that they don't break the [Rules of React](/reference/rules), which you can use `eslint-plugin-react-compiler` to identify.
200225

201226
## Usage {/*installation*/}
202227

203228
### Babel {/*usage-with-babel*/}
204229

205230
<TerminalBlock>
206-
npm install babel-plugin-react-compiler@experimental
231+
npm install babel-plugin-react-compiler@beta
207232
</TerminalBlock>
208233

209234
The compiler includes a Babel plugin which you can use in your build pipeline to run the compiler.
@@ -252,36 +277,7 @@ export default defineConfig(() => {
252277

253278
### Next.js {/*usage-with-nextjs*/}
254279

255-
Next.js has an experimental configuration to enable the React Compiler. It automatically ensures Babel is set up with `babel-plugin-react-compiler`.
256-
257-
- Install Next.js canary, which uses React 19 Release Candidate
258-
- Install `babel-plugin-react-compiler`
259-
260-
<TerminalBlock>
261-
npm install next@canary babel-plugin-react-compiler@experimental
262-
</TerminalBlock>
263-
264-
Then configure the experimental option in `next.config.js`:
265-
266-
```js {4,5,6}
267-
// next.config.js
268-
/** @type {import('next').NextConfig} */
269-
const nextConfig = {
270-
experimental: {
271-
reactCompiler: true,
272-
},
273-
};
274-
275-
module.exports = nextConfig;
276-
```
277-
278-
Using the experimental option ensures support for the React Compiler in:
279-
280-
- App Router
281-
- Pages Router
282-
- Webpack (default)
283-
- Turbopack (opt-in through `--turbo`)
284-
280+
Please refer to the [Next.js docs](https://nextjs.org/docs/canary/app/api-reference/next-config-js/reactCompiler) for more information.
285281

286282
### Remix {/*usage-with-remix*/}
287283
Install `vite-plugin-babel`, and add the compiler's Babel plugin to it:
@@ -314,40 +310,7 @@ export default defineConfig({
314310

315311
### Webpack {/*usage-with-webpack*/}
316312

317-
You can create your own loader for React Compiler, like so:
318-
319-
```js
320-
const ReactCompilerConfig = { /* ... */ };
321-
const BabelPluginReactCompiler = require('babel-plugin-react-compiler');
322-
323-
function reactCompilerLoader(sourceCode, sourceMap) {
324-
// ...
325-
const result = transformSync(sourceCode, {
326-
// ...
327-
plugins: [
328-
[BabelPluginReactCompiler, ReactCompilerConfig],
329-
],
330-
// ...
331-
});
332-
333-
if (result === null) {
334-
this.callback(
335-
Error(
336-
`Failed to transform "${options.filename}"`
337-
)
338-
);
339-
return;
340-
}
341-
342-
this.callback(
343-
null,
344-
result.code,
345-
result.map === null ? undefined : result.map
346-
);
347-
}
348-
349-
module.exports = reactCompilerLoader;
350-
```
313+
A community Webpack loader is [now available here](https://github.com/SukkaW/react-compiler-webpack).
351314

352315
### Expo {/*usage-with-expo*/}
353316

@@ -371,11 +334,15 @@ To report issues, please first create a minimal repro on the [React Compiler Pla
371334

372335
You can also provide feedback in the React Compiler Working Group by applying to be a member. Please see [the README for more details on joining](https://github.com/reactwg/react-compiler).
373336

374-
### `(0 , _c) is not a function` error {/*0--_c-is-not-a-function-error*/}
337+
### What does the compiler assume? {/*what-does-the-compiler-assume*/}
338+
339+
React Compiler assumes that your code:
375340

376-
This occurs if you are not using React 19 RC and up. To fix this, [upgrade your app to React 19 RC](https://react.dev/blog/2024/04/25/react-19-upgrade-guide) first.
341+
1. Is valid, semantic JavaScript.
342+
2. Tests that nullable/optional values and properties are defined before accessing them (for example, by enabling [`strictNullChecks`](https://www.typescriptlang.org/tsconfig/#strictNullChecks) if using TypeScript), i.e., `if (object.nullableProperty) { object.nullableProperty.foo }` or with optional-chaining `object.nullableProperty?.foo`.
343+
3. Follows the [Rules of React](https://react.dev/reference/rules).
377344

378-
If you are unable to upgrade to React 19, you may try a userspace implementation of the cache function as described in the [Working Group](https://github.com/reactwg/react-compiler/discussions/6). However, please note that this is not recommended and you should upgrade to React 19 when possible.
345+
React Compiler can verify many of the Rules of React statically, and will safely skip compilation when it detects an error. To see the errors we recommend also installing [eslint-plugin-react-compiler](https://www.npmjs.com/package/eslint-plugin-react-compiler).
379346

380347
### How do I know my components have been optimized? {/*how-do-i-know-my-components-have-been-optimized*/}
381348

src/content/reference/react/useActionState.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ In earlier React Canary versions, this API was part of React DOM and called `use
2020
`useActionState` is a Hook that allows you to update state based on the result of a form action.
2121

2222
```js
23-
const [state, formAction] = useActionState(fn, initialState, permalink?);
23+
const [state, formAction, isPending] = useActionState(fn, initialState, permalink?);
2424
```
2525
2626
</Intro>
@@ -35,7 +35,7 @@ const [state, formAction] = useActionState(fn, initialState, permalink?);
3535
3636
{/* TODO T164397693: link to actions documentation once it exists */}
3737
38-
Call `useActionState` at the top level of your component to create component state that is updated [when a form action is invoked](/reference/react-dom/components/form). You pass `useActionState` an existing form action function as well as an initial state, and it returns a new action that you use in your form, along with the latest form state. The latest form state is also passed to the function that you provided.
38+
Call `useActionState` at the top level of your component to create component state that is updated [when a form action is invoked](/reference/react-dom/components/form). You pass `useActionState` an existing form action function as well as an initial state, and it returns a new action that you use in your form, along with the latest form state and whether the Action is still pending. The latest form state is also passed to the function that you provided.
3939
4040
```js
4141
import { useActionState } from "react";
@@ -71,10 +71,11 @@ If used with a Server Action, `useActionState` allows the server's response from
7171
7272
#### Returns {/*returns*/}
7373
74-
`useActionState` returns an array with exactly two values:
74+
`useActionState` returns an array with the following values:
7575
7676
1. The current state. During the first render, it will match the `initialState` you have passed. After the action is invoked, it will match the value returned by the action.
7777
2. A new action that you can pass as the `action` prop to your `form` component or `formAction` prop to any `button` component within the form.
78+
3. The `isPending` flag that tells you whether there is a pending Transition.
7879
7980
#### Caveats {/*caveats*/}
8081
@@ -104,10 +105,11 @@ function MyComponent() {
104105
}
105106
```
106107
107-
`useActionState` returns an array with exactly two items:
108+
`useActionState` returns an array with the following items:
108109
109110
1. The <CodeStep step={1}>current state</CodeStep> of the form, which is initially set to the <CodeStep step={4}>initial state</CodeStep> you provided, and after the form is submitted is set to the return value of the <CodeStep step={3}>action</CodeStep> you provided.
110111
2. A <CodeStep step={2}>new action</CodeStep> that you pass to `<form>` as its `action` prop.
112+
3. A <CodeStep step={1}>pending state</CodeStep> that you can utilise whilst your action is processing.
111113
112114
When the form is submitted, the <CodeStep step={3}>action</CodeStep> function that you provided will be called. Its return value will become the new <CodeStep step={1}>current state</CodeStep> of the form.
113115
@@ -133,13 +135,13 @@ import { useActionState, useState } from "react";
133135
import { addToCart } from "./actions.js";
134136

135137
function AddToCartForm({itemID, itemTitle}) {
136-
const [message, formAction] = useActionState(addToCart, null);
138+
const [message, formAction, isPending] = useActionState(addToCart, null);
137139
return (
138140
<form action={formAction}>
139141
<h2>{itemTitle}</h2>
140142
<input type="hidden" name="itemID" value={itemID} />
141143
<button type="submit">Add to Cart</button>
142-
{message}
144+
{isPending ? "Loading..." : message}
143145
</form>
144146
);
145147
}
@@ -162,6 +164,10 @@ export async function addToCart(prevState, queryData) {
162164
if (itemID === "1") {
163165
return "Added to cart";
164166
} else {
167+
// Add a fake delay to make waiting noticeable.
168+
await new Promise(resolve => {
169+
setTimeout(resolve, 2000);
170+
});
165171
return "Couldn't add to cart: the item is sold out.";
166172
}
167173
}

src/content/reference/react/useReducer.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ function MyComponent() {
5252
#### Caveats {/*caveats*/}
5353
5454
* `useReducer` is a Hook, so you can only call it **at the top level of your component** or your own Hooks. You can't call it inside loops or conditions. If you need that, extract a new component and move the state into it.
55-
* The `dispatch` function has a stable identity, so you will often see it omitted from effect dependencies, but including it will not cause the effect to fire. If the linter lets you omit a dependency without errors, it is safe to do. [Learn more about removing Effect dependencies.](/learn/removing-effect-dependencies#move-dynamic-objects-and-functions-inside-your-effect)
55+
* The `dispatch` function has a stable identity, so you will often see it omitted from Effect dependencies, but including it will not cause the Effect to fire. If the linter lets you omit a dependency without errors, it is safe to do. [Learn more about removing Effect dependencies.](/learn/removing-effect-dependencies#move-dynamic-objects-and-functions-inside-your-effect)
5656
* In Strict Mode, React will **call your reducer and initializer twice** in order to [help you find accidental impurities.](#my-reducer-or-initializer-function-runs-twice) This is development-only behavior and does not affect production. If your reducer and initializer are pure (as they should be), this should not affect your logic. The result from one of the calls is ignored.
5757
5858
---

0 commit comments

Comments
 (0)