Fast Refresh
Fast Refresh 是 React Native 的一项功能,可让您近乎即时地获得 React 组件更改的反馈。Fast Refresh 默认启用,您可以在 React Native Dev 菜单中切换“启用 Fast Refresh”。启用 Fast Refresh 后,大多数编辑操作应在一两秒钟内可见。
它是如何工作的
- 如果您编辑一个仅导出 React 组件的模块,Fast Refresh 将仅更新该模块的代码,并重新渲染您的组件。您可以编辑该文件中的任何内容,包括样式、渲染逻辑、事件处理程序或效果。
- 如果您编辑的模块导出了不是 React 组件的内容,Fast Refresh 将重新运行该模块以及导入它的其他模块。因此,如果
Button.js
和Modal.js
都导入了Theme.js
,则编辑Theme.js
将更新这两个组件。 - 最后,如果您编辑一个文件,该文件被 React 树外部的模块导入,Fast Refresh 将回退到执行完全重新加载。您可能有一个文件,它渲染一个 React 组件,但也导出一个值,该值被一个非 React 组件导入。例如,您的组件也可能导出一个常量,而非 React 实用程序模块导入了它。在这种情况下,请考虑将常量迁移到单独的文件中,并将其导入到这两个文件中。这将重新启用 Fast Refresh 以使其工作。其他情况通常可以用类似的方式解决。
错误弹性
如果您在 Fast Refresh 会话期间出现语法错误,您可以修复它并再次保存文件。红框将消失。具有语法错误的模块将被阻止运行,因此您无需重新加载应用程序。
如果您在模块初始化期间出现运行时错误(例如,键入 Style.create
而不是 StyleSheet.create
),则在您修复错误后,Fast Refresh 会话将继续。红框将消失,模块将被更新。
如果您犯了一个错误,导致组件内部出现运行时错误,则在您修复错误后,Fast Refresh 会话也将继续。在这种情况下,React 将使用更新后的代码重新挂载您的应用程序。
如果您的应用程序中有错误边界(这对于生产环境中的优雅失败来说是一个好主意),它们将在红框后的下一次编辑时重试渲染。从这个意义上讲,拥有错误边界可以防止您始终被踢回根应用程序屏幕。但是,请记住,错误边界不应太精细。它们在生产环境中被 React 使用,并且应始终经过有意设计。
局限性
Fast Refresh 尝试在您正在编辑的组件中保留本地 React 状态,但前提是这样做是安全的。以下是一些您可能会看到每次编辑文件时本地状态都被重置的原因
- 本地状态不适用于类组件(只有函数组件和 Hooks 保留状态)。
- 您正在编辑的模块可能除了 React 组件之外还有其他导出。
- 有时,模块会导出调用高阶组件(如
createNavigationContainer(MyScreen)
)的结果。如果返回的组件是一个类,则状态将被重置。
从长远来看,随着您的更多代码库迁移到函数组件和 Hooks,您可以期望在更多情况下保留状态。
提示
- 默认情况下,Fast Refresh 在函数组件(和 Hooks)中保留 React 本地状态。
- 有时您可能想要强制重置状态,并重新挂载组件。例如,如果您正在调整仅在挂载时发生的动画,这可能会很有用。为此,您可以在您正在编辑的文件中的任何位置添加
// @refresh reset
。此指令是文件本地的,并指示 Fast Refresh 在每次编辑时重新挂载在该文件中定义的组件。
Fast Refresh 和 Hooks
在可能的情况下,Fast Refresh 尝试在编辑之间保留组件的状态。特别是,useState
和 useRef
会保留它们之前的值,只要您不更改它们的参数或 Hook 调用的顺序。
具有依赖项的 Hooks(例如 useEffect
、useMemo
和 useCallback
)在 Fast Refresh 期间将始终更新。当 Fast Refresh 正在进行时,它们的依赖项列表将被忽略。
例如,当您将 useMemo(() => x * 2, [x])
编辑为 useMemo(() => x * 10, [x])
时,即使 x
(依赖项)没有更改,它也会重新运行。如果 React 不这样做,您的编辑将不会反映在屏幕上!
有时,这可能会导致意外的结果。例如,即使是具有空依赖项数组的 useEffect
,在 Fast Refresh 期间仍然会重新运行一次。但是,即使没有 Fast Refresh,编写能够应对 useEffect
偶尔重新运行的代码也是一个好习惯。这使您以后更容易向其引入新的依赖项。