Skip to content

[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
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions src/content/learn/react-compiler-deep-dive-backup.md
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:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
React Compiler can also automatically memoize for expensive calculations used during rendering:
React Compiler can also automatically memoize 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>
346 changes: 0 additions & 346 deletions src/content/learn/react-compiler.md

This file was deleted.

74 changes: 74 additions & 0 deletions src/content/learn/react-compiler/compatibility.md
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' }],
],
},
}),
],
});
```

79 changes: 79 additions & 0 deletions src/content/learn/react-compiler/configuration.md
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).
93 changes: 93 additions & 0 deletions src/content/learn/react-compiler/debugging.md
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
Loading