跳至主要内容

快速刷新

快速刷新是 React Native 的一项功能,允许您获得对 React 组件更改的近乎即时的反馈。快速刷新默认启用,您可以在 React Native 开发者菜单 中切换“启用快速刷新”。启用快速刷新后,大多数编辑应该在一两秒内可见。

工作原理

  • 如果您编辑的模块**仅导出 React 组件**,快速刷新将仅更新该模块的代码并重新渲染您的组件。您可以编辑该文件中的任何内容,包括样式、渲染逻辑、事件处理程序或效果。
  • 如果您编辑的模块包含**不是** React 组件的导出,快速刷新将重新运行该模块以及导入它的其他模块。因此,如果 Button.jsModal.js 都导入 Theme.js,则编辑 Theme.js 将更新这两个组件。
  • 最后,如果您**编辑的文件**被**React 树外部的模块**导入,快速刷新将**回退到进行完全重新加载**。您可能有一个文件渲染 React 组件,但也导出由**非 React 组件**导入的值。例如,您的组件可能还导出一个常量,并且一个非 React 实用程序模块导入了它。在这种情况下,请考虑将常量迁移到单独的文件中,并将其导入这两个文件。这将重新启用快速刷新功能。其他情况通常可以用类似的方式解决。

错误恢复

如果您在快速刷新会话期间出现**语法错误**,您可以修复它并再次保存文件。红色框将消失。阻止运行出现语法错误的模块,因此您无需重新加载应用程序。

如果您在**模块初始化期间出现运行时错误**(例如,键入 Style.create 而不是 StyleSheet.create),则在您修复错误后,快速刷新会话将继续。红色框将消失,并且模块将更新。

如果您犯了一个导致**组件内部出现运行时错误**的错误,则在您修复错误后,快速刷新会话也将继续。在这种情况下,React 将使用更新的代码重新挂载您的应用程序。

如果您的应用程序中包含错误边界(这对于生产环境中的优雅故障处理是一个好主意),它们将在红色框出现后的下一次编辑时重试渲染。从这个意义上说,拥有一个错误边界可以防止您始终被踢回到根应用程序屏幕。但是,请记住,错误边界不应该过于细粒度。它们在生产环境中由 React 使用,并且应该始终被有意设计。

限制

快速刷新尝试保留您正在编辑的组件中的本地 React 状态,但前提是这样做是安全的。以下是一些您可能在每次编辑文件时看到本地状态被重置的原因

  • 类组件不保留本地状态(只有函数组件和 Hooks 保留状态)。
  • 您正在编辑的模块除了 React 组件之外可能还有其他导出。
  • 有时,模块会导出调用高阶组件(如 createNavigationContainer(MyScreen))的结果。如果返回的组件是类,则状态将被重置。

从长远来看,随着您的更多代码库迁移到函数组件和 Hooks,您可以期望在更多情况下保留状态。

提示

  • 快速刷新默认情况下保留函数组件(和 Hooks)中的 React 本地状态。
  • 有时您可能想要**强制**重置状态并重新挂载组件。例如,如果您正在调整仅在挂载时发生的动画,这将非常方便。为此,您可以在要编辑的文件中的任何位置添加 // @refresh reset。此指令特定于文件,并指示快速刷新在每次编辑时重新挂载在该文件中定义的组件。

快速刷新和 Hooks

在可能的情况下,快速刷新尝试在编辑之间保留组件的状态。特别是,useStateuseRef 保留其先前的值,只要您不更改其参数或 Hook 调用的顺序。

带有依赖项的 Hooks(例如 useEffectuseMemouseCallback)将在快速刷新期间**始终**更新。在快速刷新期间将忽略它们的依赖项列表。

例如,当您将 useMemo(() => x * 2, [x]) 编辑为 useMemo(() => x * 10, [x]) 时,它将重新运行,即使 x(依赖项)没有改变。如果 React 没有这样做,您的编辑将不会反映在屏幕上!

有时,这会导致意外的结果。例如,即使是具有空依赖项数组的 useEffect 也会在快速刷新期间重新运行一次。但是,即使没有快速刷新,编写对 useEffect 的偶尔重新运行有弹性的代码也是一个好习惯。这使得您以后更容易向其中引入新的依赖项。