调试和故障排除

本指南帮助你在使用 React 编译器时识别和解决问题。学习如何调试编译问题并解决常见问题。

你将学习到

  • 编译器错误和运行时问题之间的区别
  • 导致编译中断的常见模式
  • 逐步调试工作流程

了解编译器行为

🌐 Understanding Compiler Behavior

React 编译器旨在处理遵循 React 规则 的代码。当它遇到可能违反这些规则的代码时,它会安全地跳过优化,而不是冒改变应用行为的风险。

🌐 React Compiler is designed to handle code that follows the Rules of React. 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

编译器错误 发生在构建时,会阻止你的代码编译。这些错误比较少见,因为编译器的设计是跳过有问题的代码而不是直接失败。

运行时问题 发生在编译后的代码表现得与预期不同的时候。大多数情况下,如果你在使用 React 编译器时遇到问题,这通常是一个运行时问题。这通常发生在你的代码以编译器无法检测到的微妙方式违反了 React 的规则时,而编译器错误地编译了本应该跳过的组件。

在调试运行时问题时,应将精力集中在查找受影响组件中未被 ESLint 规则检测到的 React 规则违规行为。编译器依赖你的代码遵循这些规则,当这些规则以编译器无法检测的方式被破坏时,就会发生运行时问题。

🌐 When debugging runtime issues, focus your efforts on finding Rules of React violations in the affected components that were not detected by the ESLint rule. 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

React 编译器可能破坏你的应用的主要方式之一是,如果你的代码是依赖于 memoization(记忆化)来保证正确性的。这意味着你的应用依赖于特定的值被记忆化才能正常工作。由于编译器的记忆化方式可能与你手动实现的不同,这可能导致意外行为,例如副作用过度触发、无限循环或更新丢失。

🌐 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:

  • 依赖引用相等的效果 - 当效果依赖于对象或数组在多次渲染中保持相同引用时
  • 需要稳定引用的依赖数组 - 当不稳定的依赖导致副作用过于频繁触发或产生无限循环时
  • 基于引用检查的条件逻辑 - 当代码使用引用相等检查进行缓存或优化时

调试工作流程

🌐 Debugging Workflow

遇到问题时请遵循以下步骤:

🌐 Follow these steps when you encounter issues:

编译器构建错误

🌐 Compiler Build Errors

如果你遇到一个意外中断构建的编译器错误,这很可能是编译器的一个漏洞。请将其报告到 facebook/react 仓库,并附上:

🌐 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 repository with:

  • 错误消息
  • 导致错误的代码
  • 你的 React 和编译器版本

运行时问题

🌐 Runtime Issues

对于运行时行为问题:

🌐 For runtime behavior issues:

1. 临时禁用编译

🌐 1. Temporarily Disable Compilation

使用 "use no memo" 来隔离问题是否与编译器有关:

🌐 Use "use no memo" to isolate whether an issue is compiler-related:

function ProblematicComponent() {
"use no memo"; // Skip compilation for this component
// ... rest of component
}

如果问题消失,则可能与 React 规则违规有关。

🌐 If the issue disappears, it’s likely related to a Rules of React violation.

你也可以尝试从有问题的组件中移除手动的记忆化(useMemo、useCallback、memo),以验证你的应用在没有任何记忆化的情况下是否能正常工作。如果在移除所有记忆化后问题仍然存在,则说明你违反了 React 规则,需要修复。

🌐 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. 逐步解决问题

🌐 2. Fix Issues Step by Step

  1. 识别根本原因(通常是记忆化以确保正确性)
  2. 每次修复后进行测试
  3. 修复后移除 "use no memo"
  4. 验证组件在 React DevTools 中是否显示 ✨ 标记

报告编译器错误

🌐 Reporting Compiler Bugs

如果你认为发现了编译器 bug:

🌐 If you believe you’ve found a compiler bug:

  1. 确认这不是违反 React 规则 - 使用 ESLint 检查
  2. 创建最小可重现示例 - 在一个小例子中隔离问题
  3. 没有编译器的测试 - 确认该问题仅在编译时发生
  4. 提交一个问题
    • React 和编译器版本
    • 最小化复现代码
    • 预期行为与实际行为
    • 任何错误消息

下一步

🌐 Next Steps