React Hot Loader
React Hot Loader is a utility that enables Hot Module Replacement (HMR) for React components, allowing developers to tweak components in real time without losing application state during development. The current stable version is 4.13.1, which receives frequent bug fixes and minor updates, as evidenced by its release history. It works by patching React's reconciliation process to allow components to be swapped out without re-mounting, preserving component state and improving development efficiency. While it has been a cornerstone for many React development workflows, it is explicitly positioned as being superseded by React Fast Refresh. Users are strongly encouraged to migrate to Fast Refresh if their environment (e.g., React Native, Parcel 2, Webpack with a plugin, Create React App v4+, Next.js v9.4+) supports it, as Fast Refresh offers a more integrated and robust solution. However, React Hot Loader remains a viable option for environments that do not yet support Fast Refresh.
Common errors
-
Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
cause This often occurs if the `react-hot-loader/babel` plugin is missing, leading to issues with hook order changes, or if `react-hot-loader` is not properly patching React before it initializes.fixVerify that `react-hot-loader/babel` is correctly configured in your Babel setup and that `react-hot-loader/patch` or `import 'react-hot-loader';` is loaded as the absolute first entry point in your application. -
React-Hot-Loader: "something" is not a valid React Component.
cause React Hot Loader could not identify the exported component as a valid React component (e.g., a function component, class component, or memoized component). This can happen with incorrect exports or if a HOC wraps something that's not a component.fixEnsure that the component you are exporting (and wrapping with `hot()`) is indeed a React component. Check for typos in exports or ensure the component is fully defined before being exported and hot-wrapped. -
React-Hot-Loader: RHL could not be activated.
cause This message indicates that React Hot Loader failed to inject its patching mechanisms into React, usually because it was loaded after React/ReactDOM, or the `module.hot` API was not available.fixConfirm that `'react-hot-loader/patch'` is the very first entry in your Webpack configuration's `entry` array, or that `import 'react-hot-loader';` is the first line of code in your root application file. Also ensure that Webpack's HMR is enabled.
Warnings
- deprecated React Hot Loader is officially superseded by React Fast Refresh. For new projects or existing projects in environments that support it (e.g., React Native, Parcel 2, Webpack with `react-refresh-webpack-plugin`, Create React App v4+, Next.js v9.4+), migration to Fast Refresh is strongly recommended for better stability and experience.
- breaking The import path for the 'hot' Higher-Order Component changed in v4. Previously, it was often imported directly from 'react-hot-loader'.
- gotcha For proper hooks support and updating during HMR, you must use `@hot-loader/react-dom` by aliasing `react-dom` in your Webpack configuration. Additionally, hooks will only auto-update if they have a non-zero dependency list (e.g., `useEffect(effect, [dep])`) or if specific configuration options (`reloadHooksOnBodyChange`, `reloadLifeCycleHooks`) are enabled.
- gotcha The Babel plugin `react-hot-loader/babel` is required for React Hot Loader to function correctly, especially for handling changes in hook order without throwing errors. Without it, adding, removing, or reordering hooks might cause a React error.
- gotcha React Hot Loader or its `patch` entry point must be loaded *before* React and ReactDOM. Failing to do so will result in RHL not being able to intercept and patch React's mechanisms, leading to HMR failures.
Install
-
npm install react-hot-loader -
yarn add react-hot-loader -
pnpm add react-hot-loader
Imports
- hot
import { hot } from 'react-hot-loader';import { hot } from 'react-hot-loader/root'; - setConfig
import { setConfig } from 'react-hot-loader'; - react-hot-loader/patch
require('react-hot-loader/patch'); // inside a React componententry: ['react-hot-loader/patch', './src']
Quickstart
// .babelrc
{
"plugins": ["react-hot-loader/babel"]
}
// webpack.config.js
module.exports = {
mode: 'development',
entry: ['react-hot-loader/patch', './src/index.tsx'],
// ... other webpack config
module: {
rules: [
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: 'babel-loader'
}
]
},
resolve: {
alias: {
'react-dom': '@hot-loader/react-dom' // For hooks support
},
extensions: ['.tsx', '.ts', '.js']
}
};
// src/index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import { hot } from 'react-hot-loader/root';
const App = () => {
const [count, setCount] = React.useState(0);
React.useEffect(() => {
// This hook will reload because its dependency list is non-empty
console.log('App component mounted or count changed:', count);
}, [count, "hot"]); // Adding "hot" ensures reloadability
return (
<div>
<h1>Hello React Hot Loader!</h1>
<p>Count: {count}</p>
<button onClick={() => setCount(c => c + 1)}>Increment</button>
<p>Edit this component and save to see HMR in action.</p>
</div>
);
};
const HotApp = hot(App);
ReactDOM.render(<HotApp />, document.getElementById('root'));