question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

State isn't preserved

See original GitHub issue

I have made a demo site with the following config:

const ReactRefreshPlugin 	= require('@pmmmwh/react-refresh-webpack-plugin');
const HtmlWebpackPlugin 	= require('html-webpack-plugin');

module.exports = {
	entry: './src/index.js',
	mode: 'development',
	devtool: 'eval-cheap-module-source-map',
	devServer: {
		port: 12345,
		host: 'test.domain.com',
		watchOptions: {
			ignored: /node_modules/
		},
	},
	module: {
			rules: [
				{
					test: /\.jsx$/,
					exclude: /(node_modules|bower_components)/,
					use: [{
						loader: 'babel-loader',
						options: {
							presets: ['@babel/preset-react'],
							plugins: ['@babel/plugin-proposal-class-properties', '@babel/plugin-proposal-export-default-from', 'react-refresh/babel',],
						}
					}]
				},
			]
	},
	plugins: [new ReactRefreshPlugin(), new HtmlWebpackPlugin({template: './src/index.html', filename: 'test.html'}), ],
	resolve: {
	    extensions: ['.js', '.jsx'],
	  },
}

The port and host is dummy in above example. I have taken the files from the example dir https://github.com/pmmmwh/react-refresh-webpack-plugin/tree/master/examples/webpack-dev-server. When I change a file like ClassNamed.js, the output in the browser is refreshed without a page refresh. But the state is cleared, I think because the constructor of ClassNamed is called again. I don’t think this is the indented behavior, but what am I doing wrong?

I’m using these versions: “react”: “^16.13.1”, “webpack-dev-server”: “^3.11.0”, “react-refresh”: “^0.8.3”, “@pmmmwh/react-refresh-webpack-plugin”: “^0.3.3”,

Hope someone can help!

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

4reactions
pmmmwhcommented, Jun 11, 2020

Why is this the intended behaviour?

Class components are always remounted, and thus they can never preserve state. Fast refresh is implemented differently to react-hot-loader, and the fundamental difference means that some stuff people expect from RHL might not hold. This is one example of such things.

It’s possible with hot reloading.

I’m assuming that you’re referring to react-hot-loader.

There is a difference between “it is possible” and “it is reliable”, and the line is often blurry. Hot reloading class components was never reliable/maintainable (components might end up in an incorrect state) and it requires mutation to your source code (wrapping components with Proxies). This causes a lot of stuff to not work properly: lifecycle methods being called randomly, type checks fails randomly (<Component />.type === Component is false). Not to mention that this approach peeks into React’s internals, thus will need to play catch up with React as we move into the future with Concurrent Mode.

With all that background in mind, I don’t think it is surprising that Dan chose to not let history repeats itself (especially when function components are getting more and more powerful with Hooks). In his wish list for hot reloading (which eventually led to Fast Refresh), he clearly stated:

It is better to lose local state than to behave incorrectly. It is better to lose local state than use an old version.

However - I would suggest you still go with fast refresh instead of adopting RHL if you’re planning to move to hooks in the future. While it will not preserve state for classes, fast refresh is much more reliable and resilient to errors, and will recover correctly in most cases. It is also officially stated in the RHL README that fast refresh should be the way to go moving forward.

I hope this better explains the situation.

1reaction
dmeijcommented, Jun 11, 2020

One more question though, hope you know an answer since you’re the fast refresh master 😛. fast refresh always remounts class components and always triggers the useEffect for function components. When the component does an API call to load data, I would like it to be called only once and not at every fast refresh. Is this possible?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Local state not preserved · Issue #416 - GitHub
So, I've been having a devil of a time trying to get local state to be preserved when hot reloading modules.
Read more >
Preserving and Resetting State - React Docs
React keeps state for as long as the same component is rendered at the same position. State is not kept in JSX tags....
Read more >
State not preserved in component render() in React Native
In React Navite, I am saving an array of values from Firebase and rendering Views for each value. I cannot the values from...
Read more >
Why is page state not preserved when using browser Back ...
Put in a piece of Javascript that asks the server for the current state of the votes every time the page is loaded...
Read more >
Forwarding state not preserved on 9k after SSO in ASR903
Symptom: Forwarding state is not preserved on the Cisco ASR 9000 series router after an SSO in the Cisco ASR 903 router.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found