Several years ago, it was becoming tiring (and annoying in the case where the changes do not render as expected) to refresh the browser to see the most recent updates on a web project.
In a bid to solve this problem, developers created several plugins and tools that can cause the DOM to re-render on each save without even doing a full-reload.
This is called hot-reloading. It works by replacing a module of the application during run-time with an updated one so that it’s available for instant use.
This leads us to talk about Hot Module Replacement (HMR).
HMR, as the name implies, can replace modules without restarting the server and can easily be enabled with different bundlers.
On Webpack’s website, it says:
Hot Module Replacement (HMR) exchanges, adds, or removes modules while an application is running, without a full reload. This can significantly speed up development in a few ways.
HMR solves the problem of hot-reloading, makes it easier to tweak styling (almost comparable to changing styles in the browser’s debugger) and generally speeds up the development process.
But what happens when we live-reload in a component based framework like React that keeps track of its states? We lose the state.
The reason we lose the state can be understood by first understanding the difference between hot-reload and live-reload:
A hot reload to an app will only refresh the files that were changed without losing the application’s state.
A live reload to an app will restart the entire app, and load cause it to lose its state.
The primary aim of this tutorial is to demonstrate how we can quickly setup react-hot-loader for our React application so that its components can be live-reloaded without a loss in state.
The resulting code for this article is available here on GitHub.
Prerequisites
- Please ensure that you have Node and npm installed before starting the tutorial
- Very basic knowledge of React is assumed and a general understanding of JavaScript would be helpful
- We will be using the create-react-app tool to create the React Application
If you don’t already have the create-react-app tool on your computer, you can install it with this command:
npm install -g create-react-app
Setup the development environment
Let’s spin up a new instance of a create-react-app project and navigate into the newly created directory with these commands:
create-react-app react-hot-loader-demo
cd react-hot-loader-demo
We can run the application using this command:
npm start
This command starts the web server that points to the address localhost://3000. We will visit this address on our browser and keep the tab open because throughout this tutorial, we will be monitoring the updates and behavior of the application in the browser.
When we create a new project using the create-react-app, the Hot Module Replacement (HRM) plugin is enabled by default in the Webpack configuration file, though we can’t see this file because create-react-app configures our application for us and hides the configuration files.
Checking the hot-reload behavior
We can see the HRM’s hot-reloading in action by adding a basic style to the index.css file that’s included out of the box. We’ll add a property value pair — background: lightblue — to the body style:
body {
margin: 0;
padding: 0;
font-family: sans-serif;
background: lightblue;
}
On saving this, the application updates without the browser tab refreshing.
This behavior is possible because the HRM is able to replace a module of code in the application during run-time.
Checking the hot-reload behavior with a JavaScript file
Now let’s see what happens when we edit the content in the App.js file, we can do something as basic as replacing the "To get started, edit src/App.js and save to reload.” with “This is a tutorial to setup React Hotloader.”
This time, it can be observed that the application does a live-reload and the entire page refreshes so that the change can be implemented. This happens because the HMR is unable to decide how to handle the update to this JavaScript file.
Naturally, hot-reloads are possible when the HMR receives an update at run-time and confirms that the concerned module knows how to update itself. Where the module knows how to update itself, the HMR then goes up the import/require chain, searching for a parent module that can accept the update.
Let’s tweak our application a bit so that the HMR knows how to handle JavaScript files for hot-reloads.
In the index.js file (which is the entry point of our application) we will add this line of code:
This code will make it possible for the updates to our React components to do hot-reloads because the parent module (index.js) now knows how to accept and process the run-time updates.
Now, lets make a quick edit to the code and save it to see if the state persists, we will replace “Will the state be preserved? The value is {this.state.number}” with “Does the state persist now? The value is {this.state.number}”:
The resulting page:
This update is handled as a hot-reload and didn’t cause the browser to refresh!
Checking the hot-reload behavior with a state variable
Everything we have done has been awesome so far. Let’s see what happens when we include a basic state variable to the application, we can also add a function to make it increment on click events:
When we save this code and it hot-reloads, we can click on the buttons 12 times to increment it:
It works just as we wanted it to, however, what happens if we make an edit to the JavaScript file and save it now? It should do a hot-reload just as before and also preserve the value of the state variable, right? Let’s see about that. Let’s replace the line The current value of number is *{this.*
state
*.*
number
*}*
with Will the state be preserved? The value is *{this.*
state
*.*
number
*}*:
On saving it, we get this screen:
What just happened? Wasn’t our number equals to twelve a few seconds ago? Where did that value go? That’s right, during the hot-reload, the component unmounted and the constructor had to re-run when the component was mounted again. We lose state data even with the hot-reload features HMR gives to us.
We can handle this issue using the React Hotloader plugin and doing some configurations.
Setting up React Hot Loader
First of all, we want to eject our application so we can customize its configuration:
npm run eject
Running npm run eject copies all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. Commands like npm start and npm run build will still work, but they will point to the copied scripts so you can tweak them.
Doing this is also permanent
Next, we pull in React Hot Loader which is a plugin that allows React components to be live reloaded without the loss of state. It works with Webpack and other bundlers that support both Hot Module Replacement (HMR) and Babel plugins.
npm install --save react-hot-loader
Linux users might need to prefix this command with sudo for premission reasons
When this is done installing, we want to navigate into the config/webpack.config.dev.js
that is now available to us, add this line — plugins
**:** ['react-hot-loader/babel']
— to the Babel loader configuration. This is what it should resemble:
The next thing we want do is open our application’s entry point again and wrap the app’s top-level component inside of an <AppContainer>
. We have to import import the <AppContainer>
from react-hot-loader
first:
Let’s modify the module.hot
section so that we can also render the <AppContainer>
within it:
This modification tells the <AppContainer>
to process the module reloading and handle any errors that might be created during run-time.
The would be disabled in the production environment
Lastly, we need to require the react-hot-loader patch into our entry point file:
We require this because it’s responsible for patching the code at low-level processing.
Testing React Hot Loader
Let’s test our application to see if the state would be preserved on updates now, we can accomplish this by saving the updates we just made and running the application:
npm start
We can click on the button to increase the number variable to a number like 36:
Now, lets make a quick edit to the code and save it to see if the state persists:
This update causes the browser window to update to this:
Awesome! The state persisted despite the change we made to the document, this means that our react-hot-loader works perfectly and handles module reloading for us.
Conclusion
In this tutorial, we have gone from understanding why hot-loading is important to specify the difference between a hot-reload and a live reload. We have also seen how to quickly and easily setup a React application for hot-reload using the react-hot-loader plugin so that the value of all states present in the application can be persisted regardless of the updates made. The final code of this article is available here on GitHub.
Plug: LogRocket, a DVR for web apps
LogRocket is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.
In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single page apps.
Try it for free.
The post Setup React Hot Loader in 10 minutes appeared first on LogRocket Blog.
Top comments (0)