快速刷新
快速刷新是集成到 Next.js 中的 React 功能,它允许您在保存文件更改时实时重新加载浏览器页面,同时保持临时的客户端状态。它在所有 Next.js 应用程序(**9.4 或更高版本**)中默认启用。启用快速刷新后,大多数编辑应该在一秒钟内可见。
工作原理
- 如果您编辑的文件**仅导出 React 组件**,快速刷新将仅更新该文件中的代码,并重新渲染您的组件。您可以编辑该文件中的任何内容,包括样式、渲染逻辑、事件处理程序或效果。
- 如果您编辑的文件包含**不是 React 组件的导出**,快速刷新将重新运行该文件以及导入它的其他文件。因此,如果 `Button.js` 和 `Modal.js` 都导入 `theme.js`,则编辑 `theme.js` 将更新这两个组件。
- 最后,如果您**编辑的文件**被**React 树外部的文件导入**,快速刷新将**回退到执行完全重新加载**。您可能有一个文件渲染 React 组件,但也导出由**非 React 组件**导入的值。例如,您的组件可能还导出一个常量,并且非 React 实用程序文件导入它。在这种情况下,请考虑将常量迁移到单独的文件中,并将其导入这两个文件中。这将重新启用快速刷新以使其工作。其他情况通常可以通过类似的方式解决。
错误弹性
语法错误
如果您在开发过程中出现语法错误,您可以修复它并再次保存文件。错误将自动消失,因此您无需重新加载应用程序。**您不会丢失组件状态**。
运行时错误
如果您犯了一个导致组件内部出现运行时错误的错误,您将看到一个上下文覆盖层。修复错误将自动关闭覆盖层,无需重新加载应用程序。
如果错误不是在渲染过程中发生的,则组件状态将被保留。如果错误确实发生在渲染过程中,React 将使用更新的代码重新挂载您的应用程序。
如果您在应用程序中使用了错误边界(这对于生产环境中的优雅失败是一个好主意),它们将在渲染错误后的下一次编辑中重试渲染。这意味着使用错误边界可以防止您始终重置到根应用程序状态。但是,请记住,错误边界不应该过于细粒度。它们在生产环境中由 React 使用,并且应该始终被有意地设计。
限制
快速刷新尝试保留您正在编辑的组件中的本地 React 状态,但前提是这样做是安全的。以下是一些您可能在每次编辑文件时看到本地状态重置的原因
- 类组件不保留本地状态(只有函数组件和 Hooks 保留状态)。
- 您正在编辑的文件除了 React 组件之外可能还有其他导出。
- 有时,文件会导出调用高阶组件(如
HOC(WrappedComponent)
)的结果。如果返回的组件是类组件,则其状态将被重置。 - 匿名箭头函数,如
export default () => <div />;
会导致快速刷新不保留本地组件状态。对于大型代码库,您可以使用我们的name-default-component
代码模块。
随着您的更多代码库迁移到函数组件和 Hooks,您可以在更多情况下期望状态得到保留。
提示
- 快速刷新默认情况下会保留函数组件(和 Hooks)中的 React 本地状态。
- 有时您可能希望强制重置状态,并重新挂载组件。例如,如果您正在调整仅在挂载时发生的动画,这将非常方便。为此,您可以在正在编辑的文件中的任何位置添加
// @refresh reset
。此指令是特定于文件的,并指示快速刷新在每次编辑时重新挂载在该文件中定义的组件。 - 您可以在开发过程中将
console.log
或debugger;
放入您编辑的组件中。 - 请记住,导入区分大小写。当您的导入与实际文件名不匹配时,快速刷新和完整刷新都可能失败。例如,
'./header'
与'./Header'
。
快速刷新和 Hooks
在可能的情况下,快速刷新尝试保留编辑之间组件的状态。特别是,useState
和useRef
会保留其先前值,只要您不更改其参数或 Hook 调用的顺序。
具有依赖项的 Hooks(例如useEffect
、useMemo
和useCallback
)将在快速刷新期间始终更新。在快速刷新期间,将忽略它们的依赖项列表。
例如,当您将useMemo(() => x * 2, [x])
编辑为useMemo(() => x * 10, [x])
时,它将重新运行,即使x
(依赖项)没有更改。如果 React 没有这样做,您的编辑将不会反映在屏幕上!
有时,这可能导致意外的结果。例如,即使是具有空依赖项数组的useEffect
,在快速刷新期间也会重新运行一次。
但是,即使没有快速刷新,编写对useEffect
偶尔重新运行具有弹性的代码也是一个好习惯。它将使您以后更容易向其中引入新的依赖项,并且由React Strict Mode强制执行,我们强烈建议启用它。
这有帮助吗?