React Refresh is the core package that implements Fast Refresh, React's official hot reloading mechanism designed for a superior development experience. This feature allows developers to instantly see changes to React components without losing their local state, significantly speeding up the feedback loop during development. It achieves this by updating only the necessary component code and re-rendering, preserving state for functional components and Hooks. The `react-refresh` package itself, currently at version 0.18.0 (last published in October 2025), provides the underlying runtime and Babel transform. It is primarily consumed by bundler-specific plugins, such as `@pmmmwh/react-refresh-webpack-plugin` for Webpack or `@vitejs/plugin-react` for Vite, rather than being imported directly into application code. It maintains an active release cadence, with updates demonstrating sustainable maintenance. Fast Refresh differentiates itself from older hot-reloading solutions by being officially supported by the React team, offering greater reliability, and prioritizing safe state preservation.
npm install react-refreshVerified import paths — ran on the pinned version, not inferred.
This Vite configuration demonstrates how to set up Fast Refresh for a React project using the official `@vitejs/plugin-react`. This plugin transparently integrates `react-refresh` to provide hot module reloading during development.
Migrate class components to functional components using Hooks for full Fast Refresh benefits.
Separate non-React exports into their own files. Ensure all React components are named (not anonymous) and follow PascalCase naming conventions. Consider using `eslint-plugin-react-refresh` to enforce these rules.
Always ensure `react-refresh/babel` and any Fast Refresh bundler plugins are conditionally applied only when `process.env.NODE_ENV === 'development'` or similar development environment flags are active.
Regularly update all related packages (react, react-dom, react-refresh, and its bundler plugins) to their latest compatible versions. Use `npm ls react-refresh` or `yarn why react-refresh` to inspect the dependency tree for conflicting versions and consider `npm dedupe` or `package.json` 'overrides' if conflicts persist.
Use `// @refresh reset` only when a full remount and state reset is explicitly desired, for example, when debugging mount animations or specific lifecycle effects. Be mindful of its impact on developer experience.
Ensure `react-refresh/runtime.js` is not directly imported in your application code. This module is intended to be injected and managed by bundler plugins during development. Verify your bundler configuration is set up correctly for Fast Refresh, and that `react-refresh` is configured as a `devDependencies` (or `peerDependencies`) and handled by build tools. If using Create React App, ensure it's up to date and that `FAST_REFRESH=false` is not unintentionally set.
Verify that HMR is explicitly enabled in your bundler's development server configuration (e.g., `devServer.hot: true` in Webpack or Vite's default HMR settings). Ensure the necessary HMR plugins or settings are active in development mode.
Inspect your dependency tree using `npm ls react` or `yarn why react` to identify duplicate or conflicting React versions. Use `npm dedupe` or `yarn resolutions` in `package.json` to force a single, consistent React version across your project. Ensure you are using the latest compatible versions of React, React DOM, and all related Fast Refresh plugins.
For code paths that require Babel transformation with `react-refresh/babel` but are not part of the main application bundle (and thus miss the runtime injection), manually 'polyfill' these globals at the entry point of that specific code path (e.g., `self.$RefreshReg$ = () => {}; self.$RefreshSig$ = () => () => {};`). Additionally, ensure any components or variables in such indirect paths that don't render React are not named in PascalCase, to prevent the Babel plugin from processing them unnecessarily.