Create React App is great, but the projects it generates don’t have Hot Module Replacement (HMR) set up by default.

Read on for how to get it working.

The Plain Webpack Way

With just 3 lines of code, you can turn on HMR, but with one big caveat: React state and DOM state are not preserved between reloads. This is kind of a bummer.

You can add these lines to index.js to turn on standard Webpack HMR that doesn’t preserve state between reloads:

if ( module .hot ) { module . hot . accept () ; }

State Is Reset

When I originally wrote this article, I had been using this method and it seemed to be working. But after doing a test with hot reloading combined with a bit of state (spurred by a comment on Reddit), seeing that did not actually preserve state was disappointing.

I think the reason it appeared to work was because my app stores almost all of its state in Redux, and after a hot reload, the Redux actions were replayed by Redux DevTools, and the app was left in the same state as before the hot reload.

The react-hot-loader Way

You can “rewire” Create React App without ejecting, which will allow you to enable real hot module reloading. This relies on react-app-rewired and react-app-rewire-hot-loader, along with Dan Abramov’s react-hot-loader.

For more detail on the differences between the Webpack way and react-hot-loader, read this post by Mark Erikson.

And as they say in the react-app-rewired README…

By doing this you’re breaking the “guarantees” that CRA provides. That is to say you now “own” the configs. No support will be provided. Proceed with caution.

Here we go.

Install these 3 packages:

yarn add react-app-rewired react-app-rewire-hot-loader react-hot-loader

Create a file called config-overrides.js in the root directory of your project (not under “src”) with this code:

const rewireReactHotLoader = require ( 'react-app-rewire-hot-loader' ) ; module . exports = function override ( config , env ) { config = rewireReactHotLoader ( config, env ) ; return config ; }

Change index.js accordingly:

import React from 'react' ; import ReactDOM from 'react-dom' ; import './index.css' ; import App from './App' ; import registerServiceWorker from './registerServiceWorker' ; // Add this import: import { AppContainer } from 'react-hot-loader' ; // Wrap the rendering in a function: const render = () => { ReactDOM . render ( // Wrap App inside AppContainer < AppContainer > < App /> </ AppContainer > , document . getElementById ( 'root' ) ) ; } ; // Do this once registerServiceWorker () ; // Render once render () ; // Webpack Hot Module Replacement API if ( module .hot ) { module . hot . accept ( './App' , () => { render () ; }) ; }

Change package.json to use react-app-rewired instead of react-scripts. In the “scripts” section, change this:

"scripts" : { "start" : "react-scripts start" , "build" : "react-scripts build" , "test" : "react-scripts test --env=jsdom" }

To this:

"scripts" : { "start" : "react-app-rewired start" , "build" : "react-app-rewired build" , "test" : "react-app-rewired test --env=jsdom" }

Now when you start up the app, it will pass the Webpack config through react-app-rewired, through config-overrides.js and the rewire-hot-loader library, and then react-hot-loader and its AppContainer component will make hot reloading work properly. Give it a try!

Success! Now check your email. Learn the basics of React in 5 days Finally understand how React works! You will: 🎉 Get something on screen 💄 Write dynamic components 🏃 Make it interactive 😎 Fetch real data 🛳 Put it online 5 days, 5 emails. Walk away with the basics and a plan! Get Lesson 1 right now 👇 There was an error submitting your subscription. Please try again. Email Address I respect your email privacy. Unsubscribe any time. Before we go on, I have to ask... consent

There was an error submitting your subscription. Please try again.