|
| 1 | +--- |
| 2 | +source-updated-at: 2025-05-16T04:52:11.000Z |
| 3 | +translation-updated-at: 2025-05-19T22:46:30.445Z |
| 4 | +title: 快速刷新 (Fast Refresh) |
| 5 | +description: 快速刷新 (Fast Refresh) 是一种热模块替换 (HMR) 体验,能在您编辑 React 组件时提供即时反馈。 |
| 6 | +--- |
| 7 | + |
| 8 | +快速刷新 (Fast Refresh) 是 Next.js 集成的 React 功能,当您保存文件变更时,可以在保持客户端临时状态的同时实时重载浏览器页面。该功能在 **9.4 及以上版本** 的所有 Next.js 应用中默认启用。启用后,大多数编辑操作的效果都能在一秒内可见。 |
| 9 | + |
| 10 | +## 工作原理 |
| 11 | + |
| 12 | +- 如果您编辑的文件 **仅导出 React 组件**,快速刷新会仅更新该文件的代码并重新渲染对应组件。您可以修改该文件内的任何内容,包括样式、渲染逻辑、事件处理函数或副作用 (effects)。 |
| 13 | +- 如果您编辑的文件包含 _非_ React 组件的导出,快速刷新会重新执行该文件及其所有导入文件。例如 `Button.js` 和 `Modal.js` 都导入了 `theme.js`,那么编辑 `theme.js` 会同时更新这两个组件。 |
| 14 | +- 最后,如果您编辑的文件被 **React 组件树之外的文件导入**,快速刷新 **将回退为完全重载**。例如某个文件既渲染 React 组件,又导出一个被 **非 React 组件** 导入的值。这种情况下,建议将该常量迁移到独立文件,然后由原文件和工具文件共同导入。其他类似情况通常也可用相同方式解决。 |
| 15 | + |
| 16 | +## 错误恢复能力 |
| 17 | + |
| 18 | +### 语法错误 |
| 19 | + |
| 20 | +开发过程中出现语法错误时,修复后再次保存文件即可。错误会自动消失,无需重载应用。**组件状态不会丢失**。 |
| 21 | + |
| 22 | +### 运行时错误 |
| 23 | + |
| 24 | +如果组件内发生运行时错误,会出现上下文错误遮罩。修复错误后遮罩会自动消失,无需重载应用。 |
| 25 | + |
| 26 | +若错误未发生在渲染阶段,组件状态会被保留;若发生在渲染阶段,React 会使用更新后的代码重新挂载应用。 |
| 27 | + |
| 28 | +如果应用中配置了 [错误边界 (Error Boundary)](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary)(这在生产环境中能实现优雅降级),渲染错误后的下一次编辑会触发重试渲染。这意味着错误边界可以避免应用状态总是重置到根状态。但请注意错误边界不应_过度_细分,它们在 React 生产模式中有特定用途,应当谨慎设计。 |
| 29 | + |
| 30 | +## 限制 |
| 31 | + |
| 32 | +快速刷新会尽量保留编辑组件的本地 React 状态,但仅在安全时生效。以下情况会导致文件编辑时本地状态被重置: |
| 33 | + |
| 34 | +- 类组件 (class components) 的状态不会被保留(仅函数组件和 Hooks 能保留状态) |
| 35 | +- 编辑的文件可能包含 React 组件之外的_其他_导出 |
| 36 | +- 某些文件可能导出高阶组件 (HOC) 的调用结果如 `HOC(WrappedComponent)`,若返回的是类组件,其状态会被重置 |
| 37 | +- 匿名箭头函数如 `export default () => <div />;` 会导致快速刷新无法保留组件状态。大型代码库可使用 [`name-default-component` 代码迁移工具](/docs/pages/guides/upgrading/codemods#name-default-component) |
| 38 | + |
| 39 | +随着代码库向函数组件和 Hooks 迁移,状态保留的覆盖率将提升。 |
| 40 | + |
| 41 | +## 使用技巧 |
| 42 | + |
| 43 | +- 快速刷新默认会保留函数组件(及 Hooks)的 React 本地状态 |
| 44 | +- 有时您可能需要_强制_重置状态并重新挂载组件(例如调试仅会在挂载时触发的动画)。此时可在编辑文件中任意位置添加 `// @refresh reset` 指令。该指令仅作用于当前文件,会令快速刷新在每次编辑时重新挂载该文件定义的组件 |
| 45 | +- 开发期间可在编辑的组件中添加 `console.log` 或 `debugger;` |
| 46 | +- 注意导入语句区分大小写。当导入路径与实际文件名不匹配时(如 `'./header'` 与 `'./Header'`),快速刷新和完全重载都可能失败 |
| 47 | + |
| 48 | +## 快速刷新与 Hooks |
| 49 | + |
| 50 | +在可能的情况下,快速刷新会尝试保留组件状态。特别是 `useState` 和 `useRef` 会保留之前的值,只要不修改它们的参数或 Hooks 调用顺序。 |
| 51 | + |
| 52 | +具有依赖项的 Hooks(如 `useEffect`、`useMemo` 和 `useCallback`)在快速刷新期间会_始终_更新,此时它们的依赖项数组会被忽略。 |
| 53 | + |
| 54 | +例如将 `useMemo(() => x * 2, [x])` 编辑为 `useMemo(() => x * 10, [x])` 时,即使依赖项 `x` 未变化也会重新执行。若不如此,编辑结果就无法反映到界面上! |
| 55 | + |
| 56 | +有时这会导致意外结果,例如即使 `useEffect` 的依赖项数组为空,在快速刷新期间仍会执行一次。 |
| 57 | + |
| 58 | +但编写能适应 `useEffect` 偶尔重新运行的代码是良好实践,这与是否使用快速刷新无关。这能方便后续添加新依赖项,也是我们强烈推荐的 [React 严格模式 (React Strict Mode)](/docs/pages/api-reference/config/next-config-js/reactStrictMode) 所要求的。 |
0 commit comments