-
Notifications
You must be signed in to change notification settings - Fork 7.7k
[compiler] Rewrite React Compiler Docs #7868
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
poteto
wants to merge
1
commit into
main
Choose a base branch
from
pr7868
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,292
−349
Draft
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
<DeepDive> | ||
#### What kind of memoization does React Compiler add? {/*what-kind-of-memoization-does-react-compiler-add*/} | ||
|
||
The initial release of React Compiler is primarily focused on **improving update performance** (re-rendering existing components), so it focuses on these two use cases: | ||
|
||
1. **Skipping cascading re-rendering of components** | ||
* Re-rendering `<Parent />` causes many components in its component tree to re-render, even though only `<Parent />` has changed | ||
1. **Skipping expensive calculations from outside of React** | ||
* For example, calling `expensivelyProcessAReallyLargeArrayOfObjects()` inside of your component or hook that needs that data | ||
|
||
#### Optimizing Re-renders {/*optimizing-re-renders*/} | ||
|
||
React lets you express your UI as a function of their current state (more concretely: their props, state, and context). In its current implementation, when a component's state changes, React will re-render that component _and all of its children_ — unless you have applied some form of manual memoization with `useMemo()`, `useCallback()`, or `React.memo()`. For example, in the following example, `<MessageButton>` will re-render whenever `<FriendList>`'s state changes: | ||
|
||
```javascript | ||
function FriendList({ friends }) { | ||
const onlineCount = useFriendOnlineCount(); | ||
if (friends.length === 0) { | ||
return <NoFriends />; | ||
} | ||
return ( | ||
<div> | ||
<span>{onlineCount} online</span> | ||
{friends.map((friend) => ( | ||
<FriendListCard key={friend.id} friend={friend} /> | ||
))} | ||
<MessageButton /> | ||
</div> | ||
); | ||
} | ||
``` | ||
[_See this example in the React Compiler Playground_](https://playground.react.dev/#N4Igzg9grgTgxgUxALhAMygOzgFwJYSYAEAYjHgpgCYAyeYOAFMEWuZVWEQL4CURwADrEicQgyKEANnkwIAwtEw4iAXiJQwCMhWoB5TDLmKsTXgG5hRInjRFGbXZwB0UygHMcACzWr1ABn4hEWsYBBxYYgAeADkIHQ4uAHoAPksRbisiMIiYYkYs6yiqPAA3FMLrIiiwAAcAQ0wU4GlZBSUcbklDNqikusaKkKrgR0TnAFt62sYHdmp+VRT7SqrqhOo6Bnl6mCoiAGsEAE9VUfmqZzwqLrHqM7ubolTVol5eTOGigFkEMDB6u4EAAhKA4HCEZ5DNZ9ErlLIWYTcEDcIA) | ||
|
||
React Compiler automatically applies the equivalent of manual memoization, ensuring that only the relevant parts of an app re-render as state changes, which is sometimes referred to as "fine-grained reactivity". In the above example, React Compiler determines that the return value of `<FriendListCard />` can be reused even as `friends` changes, and can avoid recreating this JSX _and_ avoid re-rendering `<MessageButton>` as the count changes. | ||
|
||
#### Expensive calculations also get memoized {/*expensive-calculations-also-get-memoized*/} | ||
|
||
React Compiler can also automatically memoize for expensive calculations used during rendering: | ||
|
||
```js | ||
// **Not** memoized by React Compiler, since this is not a component or hook | ||
function expensivelyProcessAReallyLargeArrayOfObjects() { /* ... */ } | ||
|
||
// Memoized by React Compiler since this is a component | ||
function TableContainer({ items }) { | ||
// This function call would be memoized: | ||
const data = expensivelyProcessAReallyLargeArrayOfObjects(items); | ||
// ... | ||
} | ||
``` | ||
[_See this example in the React Compiler Playground_](https://playground.react.dev/#N4Igzg9grgTgxgUxALhAejQAgFTYHIQAuumAtgqRAJYBeCAJpgEYCemASggIZyGYDCEUgAcqAGwQwANJjBUAdokyEAFlTCZ1meUUxdMcIcIjyE8vhBiYVECAGsAOvIBmURYSonMCAB7CzcgBuCGIsAAowEIhgYACCnFxioQAyXDAA5gixMDBcLADyzvlMAFYIvGAAFACUmMCYaNiYAHStOFgAvk5OGJgAshTUdIysHNy8AkbikrIKSqpaWvqGIiZmhE6u7p7ymAAqXEwSguZcCpKV9VSEFBodtcBOmAYmYHz0XIT6ALzefgFUYKhCJRBAxeLcJIsVIZLI5PKFYplCqVa63aoAbm6u0wMAQhFguwAPPRAQA+YAfL4dIloUmBMlODogDpAA) | ||
|
||
However, if `expensivelyProcessAReallyLargeArrayOfObjects` is truly an expensive function, you may want to consider implementing its own memoization outside of React, because: | ||
|
||
- React Compiler only memoizes React components and hooks, not every function | ||
- React Compiler's memoization is not shared across multiple components or hooks | ||
|
||
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. | ||
</DeepDive> |
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
--- | ||
title: Backwards Compatibility | ||
--- | ||
|
||
<Intro> | ||
React Compiler works best with React 19, but it also supports React 17 and 18 with additional configuration. | ||
</Intro> | ||
|
||
<YouWillLearn> | ||
|
||
* How to configure React Compiler for React 17 and 18 | ||
|
||
</YouWillLearn> | ||
|
||
## Using React Compiler with React 17 or 18 {/*using-react-compiler-with-react-17-or-18*/} | ||
|
||
React Compiler works out of the box with React 19. For React 17 or 18, you need two things: | ||
|
||
### 1. Install the runtime package {/*install-runtime-package*/} | ||
|
||
<TerminalBlock> | ||
npm install react-compiler-runtime@rc | ||
</TerminalBlock> | ||
|
||
### 2. Configure the target version {/*configure-target-version*/} | ||
|
||
```js {5} | ||
// babel.config.js | ||
module.exports = { | ||
plugins: [ | ||
['babel-plugin-react-compiler', { | ||
target: '18', // or '17' for React 17 | ||
}], | ||
], | ||
}; | ||
``` | ||
|
||
Always use the major version number as a string for the `target` option. Use `'17'` not `17` or `'17.0.2'`. | ||
|
||
## Framework-specific configuration {/*framework-specific-configuration*/} | ||
|
||
### Next.js {/*nextjs*/} | ||
|
||
```js {5} | ||
// next.config.js | ||
module.exports = { | ||
experimental: { | ||
reactCompiler: { | ||
target: '18', | ||
}, | ||
}, | ||
}; | ||
``` | ||
|
||
### Vite {/*vite*/} | ||
|
||
```js {10} | ||
// vite.config.js | ||
import { defineConfig } from 'vite'; | ||
import react from '@vitejs/plugin-react'; | ||
|
||
export default defineConfig({ | ||
plugins: [ | ||
react({ | ||
babel: { | ||
plugins: [ | ||
['babel-plugin-react-compiler', { target: '17' }], | ||
], | ||
}, | ||
}), | ||
], | ||
}); | ||
``` | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
--- | ||
title: Configuration | ||
--- | ||
|
||
<Intro> | ||
React Compiler is designed to work out of the box with no configuration needed. Most users will not need to configure the compiler. However, if you need to customize its behavior, various configuration options are available. | ||
</Intro> | ||
|
||
<YouWillLearn> | ||
|
||
* Available configuration options | ||
* How to configure the compiler | ||
|
||
</YouWillLearn> | ||
|
||
## Configuration Options Overview {/*configuration-options-overview*/} | ||
|
||
React Compiler accepts several options to customize its behavior. See the [API reference](/reference/react/react-compiler) for detailed documentation of each option. | ||
|
||
- **`compilationMode`** - Controls which functions to compile | ||
- **`target`** - Specifies the React version for compatibility (17, 18, or 19) | ||
- **`sources`** - Limits compilation to specific files or directories | ||
- **`gating`** - Enables runtime feature flags for [incremental adoption](/learn/react-compiler/incremental-adoption) | ||
- **`logger`** - Configures logging output for debugging | ||
- **`panicThreshold`** - Sets when the compiler should halt on errors | ||
- **`noEmit`** - Disables code generation | ||
|
||
## Basic Configuration {/*basic-configuration*/} | ||
|
||
Pass options to the Babel plugin: | ||
|
||
```js | ||
// babel.config.js | ||
module.exports = { | ||
plugins: [ | ||
['babel-plugin-react-compiler', { | ||
target: '18', // For React 18 compatibility | ||
}], | ||
], | ||
}; | ||
``` | ||
|
||
## Framework Examples {/*framework-examples*/} | ||
|
||
### Next.js {/*nextjs*/} | ||
|
||
```js | ||
// next.config.js | ||
module.exports = { | ||
experimental: { | ||
reactCompiler: { | ||
target: '18', | ||
}, | ||
}, | ||
}; | ||
``` | ||
|
||
### Vite {/*vite*/} | ||
|
||
```js | ||
// vite.config.js | ||
export default { | ||
plugins: [ | ||
react({ | ||
babel: { | ||
plugins: [ | ||
['babel-plugin-react-compiler', { /* options */ }], | ||
], | ||
}, | ||
}), | ||
], | ||
}; | ||
``` | ||
|
||
## Learn More {/*learn-more*/} | ||
|
||
For detailed documentation of all configuration options, see the [React Compiler API reference](/reference/react/react-compiler). | ||
|
||
For incremental adoption strategies using these options, see the [incremental adoption guide](/learn/react-compiler/incremental-adoption). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
--- | ||
title: Debugging and Troubleshooting | ||
--- | ||
|
||
<Intro> | ||
This guide helps you identify and fix issues when using React Compiler. Learn how to debug compilation problems and resolve common issues. | ||
</Intro> | ||
|
||
<YouWillLearn> | ||
|
||
* The difference between compiler errors and runtime issues | ||
* Common patterns that break compilation | ||
* Step-by-step debugging workflow | ||
|
||
</YouWillLearn> | ||
|
||
## Understanding Compiler Behavior {/*understanding-compiler-behavior*/} | ||
|
||
React Compiler is designed to handle code that follows the [Rules of React](/reference/rules). When it encounters code that might break these rules, it safely skips optimization rather than risk changing your app's behavior. | ||
|
||
### Compiler Errors vs Runtime Issues {/*compiler-errors-vs-runtime-issues*/} | ||
|
||
**Compiler errors** occur at build time and prevent your code from compiling. These are rare because the compiler is designed to skip problematic code rather than fail. | ||
|
||
**Runtime issues** occur when compiled code behaves differently than expected. Most of the time, if you encounter an issue with React Compiler, it's a runtime issue. This typically happens when your code violates the Rules of React in subtle ways that the compiler couldn't detect, and the compiler mistakenly compiled a component it should have skipped. | ||
|
||
When debugging runtime issues, focus your efforts on finding Rules of React violations in the affected components. The compiler relies on your code following these rules, and when they're broken in ways it can't detect, that's when runtime problems occur. | ||
|
||
|
||
## Common Breaking Patterns {/*common-breaking-patterns*/} | ||
|
||
One of the main ways React Compiler can break your app is if your code was written to rely on memoization for correctness. This means your app depends on specific values being memoized to work properly. Since the compiler may memoize differently than your manual approach, this can lead to unexpected behavior like effects over-firing, infinite loops, or missing updates. | ||
|
||
Common scenarios where this occurs: | ||
|
||
- **Effects that rely on referential equality** - When effects depend on objects or arrays maintaining the same reference across renders | ||
- **Dependency arrays that need stable references** - When unstable dependencies cause effects to fire too often or create infinite loops | ||
- **Conditional logic based on reference checks** - When code uses referential equality checks for caching or optimization | ||
|
||
## Debugging Workflow {/*debugging-workflow*/} | ||
|
||
Follow these steps when you encounter issues: | ||
|
||
### Compiler Build Errors {/*compiler-build-errors*/} | ||
|
||
If you encounter a compiler error that unexpectedly breaks your build, this is likely a bug in the compiler. Report it to the [facebook/react](https://github.com/facebook/react/issues) repository with: | ||
- The error message | ||
- The code that caused the error | ||
- Your React and compiler versions | ||
|
||
### Runtime Issues {/*runtime-issues*/} | ||
|
||
For runtime behavior issues: | ||
|
||
### 1. Temporarily Disable Compilation {/*temporarily-disable-compilation*/} | ||
|
||
Use `"use no memo"` to isolate whether an issue is compiler-related: | ||
|
||
```js | ||
function ProblematicComponent() { | ||
"use no memo"; // Skip compilation for this component | ||
// ... rest of component | ||
} | ||
``` | ||
|
||
If the issue disappears, it's likely related to a Rules of React violation. | ||
|
||
You can also try removing manual memoization (useMemo, useCallback, memo) from the problematic component to verify that your app works correctly without any memoization. If the bug still occurs when all memoization is removed, you have a Rules of React violation that needs to be fixed. | ||
|
||
### 2. Fix Issues Step by Step {/*fix-issues-step-by-step*/} | ||
|
||
1. Identify the root cause (often memoization-for-correctness) | ||
2. Test after each fix | ||
3. Remove `"use no memo"` once fixed | ||
4. Verify the component shows the ✨ badge in React DevTools | ||
|
||
## Reporting Compiler Bugs {/*reporting-compiler-bugs*/} | ||
|
||
If you believe you've found a compiler bug: | ||
|
||
1. **Verify it's not a Rules of React violation** - Check with ESLint | ||
2. **Create a minimal reproduction** - Isolate the issue in a small example | ||
3. **Test without the compiler** - Confirm the issue only occurs with compilation | ||
4. **File an [issue](https://github.com/facebook/react/issues/new?template=compiler_bug_report.yml)**: | ||
- React and compiler versions | ||
- Minimal reproduction code | ||
- Expected vs actual behavior | ||
- Any error messages | ||
|
||
## Next Steps {/*next-steps*/} | ||
|
||
- Review the [Rules of React](/reference/rules) to prevent issues | ||
- Check the [incremental adoption guide](/learn/react-compiler/incremental-adoption) for gradual rollout strategies |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.