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.

Bug: function component is unmount and mount with old state when hmr

See original GitHub issue

React version: 16.13.1 react-refresh version: 0.8.1 react-refresh-webpack-plugin version: 0.3.0-beta.6

Steps To Reproduce

  1. run examples/webpack-dev-server
  2. change file examples/webpack-dev-server/src/ClassDefault.js examples/webpack-dev-server/src/FunctionDefault.js
  3. try hmr

Link to code example:

import * as React from 'react';

class ClassDefault extends React.Component {
  constructor(props) {
    super(props);
    console.log('init class');
    this.state = { state: 1 };
  }
  componentDidMount() {
    console.log('class mount');
  }

  componentWillUnmount() {
    console.log('class unmount');
  }
  render() {
    const { state } = this.state;
    return (
      <div>
        {state}
        <h1>Default Export Class1</h1>
        <div onClick={() => this.setState({ state: state + 1 })}>add</div>
      </div>
    );
  }
}

export default ClassDefault;

import * as React from 'react';

function FunctionDefault() {
  const [count, setCount] = React.useState(() => {
    console.log('init function');
    return 1;
  });
  React.useEffect(() => {
    console.log('function mount')
    return function cleanup() {
      console.log('function unmount');
    };
  }, []);
  return <div>
      <h1>Default Export Function {count}</h1>
      <div onClick={() => setCount(count + 1)}>add</div>
    </div>;
}

export default FunctionDefault;

The current behavior

class component will be unmount and mount with a brand new state when hmr. function component will be unmount and mount with old state when hmr.

console shown as below

[HMR] Updated modules:
main.js:56904 [HMR]  - ./src/ClassDefault.jsx
main.js:56904 [HMR] App is up to date.
main.0184bba375bf67f96cbd.hot-update.js:49 init class
main.js:57776 class unmount
main.0184bba375bf67f96cbd.hot-update.js:59 class mount
2main.js:56103 [WDS] App updated. Recompiling...
main.js:56642 [WDS] App hot update...
main.js:56904 [HMR] Checking for updates on the server...
main.js:62 XHR finished loading: GET "http://localhost:8080/ae89c6a9d927efd1cde1.hot-update.json".
(anonymous) @ main.js:62
hotDownloadManifest @ main.js:53
hotCheck @ main.js:296
check @ main.js:56964
(anonymous) @ main.js:57038
emit @ main.js:10952
reloadApp @ main.js:56646
ok @ main.js:56167
(anonymous) @ main.js:56414
sock.onmessage @ main.js:56026
EventTarget.dispatchEvent @ main.js:47130
(anonymous) @ main.js:47848
SockJS._transportMessage @ main.js:47846
EventEmitter.emit @ main.js:47046
WebSocketTransport.ws.onmessage @ main.js:49922
main.js:56904 [HMR] Updated modules:
main.js:56904 [HMR]  - ./src/FunctionDefault.jsx
main.js:56904 [HMR] App is up to date.
main.js:57936 function unmount
main.ae89c6a9d927efd1cde1.hot-update.js:42 function mount

The expected behavior

function component should be unmount and mount with a brand new state when hmr.

Thanks for your help.

Issue Analytics

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

github_iconTop GitHub Comments

5reactions
gaearoncommented, May 9, 2020

The current behavior is correct. The state is preserved, but effects re-run.

Try to stop thinking about effects as “mount” and “unmount”. This isn’t the right mental model for them. Effects are more about “synchronizing some values with some side effect”. In that sense, it makes sense that we want to resynchronize them if the code changes.

0reactions
pmmmwhcommented, Jul 22, 2020

It will not work correctly in this scenario

What do you expect to happen?

The effect callback is not the same as un-mount. It only means the effect was flushed and reinitialized.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How can I check if the component is unmounted in a functional ...
You can use a ref like this: const mounted = useRef(false); useEffect(() => { mounted.current = true; return () => { mounted.current =...
Read more >
React: Prevent state updates on unmounted components
In the above case, React tries to set the state of an unmounted component, which is not necessary since the component is not...
Read more >
React Reload Component
When you change the state, React knows that the component is out-of-date and ... will have to unmount the component and mount it...
Read more >
Why you should always Cleanup Side Effects in React ...
The cleanup function is a way of "cleaning up stuff" before the next thing happens. The next thing can be the component unmounting,...
Read more >
How best to use with React.StrictMode? - Questions - Babylon.js
It works except for an issue/bug with skybox seemingly not being fully disposed and/or webgl state. But again, means reinitializing babylonjs ...
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