React Fast Refresh

lxf2023-07-14 21:00:02

前言

首先介绍一下 Live reloadingHot reloading 的区别:

  • Live reloading: 修改文件之后,Webpack 重新编译,并强制刷新浏览器,属于全局(整个应用)刷新,相当于 window.location.reload()
  • Hot reloading: 修改文件之后,Webpack 重新编译对应模块,刷新时可以记住应用的状态,从而做到局部刷新。

简介

Fast Refresh 是 React 官方在 React Native(v0.6.1) 推出的模块热替换(HMR)方案,由于其核心实现与平台无关,因而 Fast Refresh 同时也可以适用于 Web。

刷新策略

  • 如果你编辑了一个 仅导出 React 组件 的模块文件, Fast Refresh 只会更新该模块的代码,并且重新渲染你的组件。你能够编辑文件里面的任何东西,包括样式,渲染逻辑,事件处理或者 effects。
  • 如果你编辑的模块并不导出 React 组件, Fast Refresh 将会重新运行该模块,和其他引入该模块的模块文件。例如,Button.jsModal.js 同时引入了 Theme.js ,编辑 theme.js 的时候,Button.jsModal.js 都会更新。
  • 最后,如果你编辑了某个文件,而这个文件被 React 渲染树 之外的模块引入,则 Fast Refresh 将会回退到完全刷新。你可能有一个文件,该文件渲染了一个 React 组件,同时又导出了一个被其他非 React 组件引入的值。例如,你的 React 组件模块同时导出了一个常量,并且在非 React 组件模块引入了它。在这种情况下面,考虑将查询迁移到一个单独的文件并将其导入到两个文件中。这样 Fast Refresh 才能重新生效。其他的情况也类似。

容错处理

  • 如果在 Fast Refresh 的过程中出现了语法错误,可以在修复错误后重新保存文件。Redbox警告会跟着消失。错误语法的模块会被阻止运行,这样你就不需要重载 App。
  • 如果出现了在模块初始化过程中的运行时错误(例如,将StyleSheet.create打成了Style.create),在你修复错误之后, Fast Refresh 会话会继续进行。Redbox 警告消失,模块更新。
  • 如果出现了组件内部发生的运行时错误,在你修复错误之后, Fast Refresh 会话将继续进行。在这种情况下,React 将会使用更新后的代码重新挂载你的应用。
  • 如果发生运行时错误的组件在 错误边界(Error Boundaries)内部, Fast Refresh 将在你修复错误后重新渲染错误边界内的节点

限制

当你编辑文件的时候,Fast Refresh 会在安全的前提下保持组件里的 state。在以下情况编辑文件之后,组件里的 state 会被重置:

  • class 组件的本地 state 不会被保持(仅保持函数组件和 Hooks 的 state)。
  • 除了 React 组件外,您正在编辑的模块可能还有其他导出。
  • 有时候,一个模块导出的是一个高阶组件,例如 createNavigationContainer(MyScreen)。如果返回的组件是一个 class 组件,state 将会被重置。

随着函数组件和 Hooks 被应用得更加广泛,从长远来看,Fast Refresh 的编辑体验会变得更好。

提示

  • Fast Refresh 默认保持函数组件(和 Hooks)的 state。
  • 假设你正在调试一个仅发生在挂载期间的动画,你想要强制重置状态,让这个组件被重新挂载。在这种场景下,你可以在文件的任何地方增加 // @refresh reset。这个指令会让 Fast Refresh 在每次编辑时重新挂载该文件中定义的组件。

Hooks

Fast Refresh 会尽可能的在编辑刷新时保留组件的状态。特别是 useStateuseRef,只要你不更改它们的参数或 Hooks 的调用顺序,就可以保留它们以前的值

有依赖的 Hook —— 比如 useEffect, useMemo, 和 useCallback在 Fast Refresh 期间将始终刷新。在 Fast Refresh 触发时它们的依赖项列表将被忽略。

举个