Breaks if adding/removing/replacing hooks
TotooriaHyperion opened this issue · comments
If you are reporting a bug or having an issue setting up React Hot Loader, please fill in below. For feature requests, feel free to remove this template entirely.
Description
What you are reporting:
import React, { useEffect, useState } from "react";
import { hot } from "react-hot-loader/root";
export default hot(
React.memo(function App() {
// + const [_0] = useState(0);
useEffect(() => {
console.log("app first render");
return () => {
console.log("app will unmount");
};
}, []);
useEffect(() => {
console.log("app updated");
return () => {
console.log("app before update");
};
});
return <>App</>;
}),
);
simply add a useState, then hmr breaks.
Expected behavior
What you think should happen:
Destory the old Component with 2 useEffect, and render a new Component with useState + 2 useEffect.
Actual behavior
What actually happens:
Throws error:
Uncaught Invariant Violation: Should have a queue. This is likely a bug in React. Please file an issue.
Warning: React has detected a change in the order of Hooks called by App. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks: https://fb.me/rules-of-hooks
Previous render Next render
-
useEffect useState
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^in App (created by HotExportedComponent)
in AppContainer (created by HotExportedComponent)
in HotExportedComponent
Environment
React Hot Loader version:
"@hot-loader/react-dom": "^16.10.2",
"react-hot-loader": "^4.12.15",
Run these commands in the project folder and fill in their results:
node -v
:v10.16.0npm -v
:6.12.0
Then, specify:
- Operating system:Mac OS 10.14.5
- Browser and version:Chrome 77.0.3865.90
Reproducible Demo
Please take the time to create a new project that reproduces the issue.
You can copy your project that experiences the problem and start removing things until you’re left with the minimal reproducible demo. This helps contributors, and you might get to the root of your problem during that process.
Push to GitHub and paste the link here.
Strange. That should work...
When I comment out the useState, everything goes fine without reload the page.
I think changing effect should cause Component to change, then react's diff algorithm should have known this component has changed, and will destroy the old one and render the new one.
I also find that when I save file first time, I got that error, but I save it again without any change, it renders the new component.
This is my entry:
const main = [
`webpack-hot-middleware/client?path=${publicPath}webpack_hot&timeout=5000&overlay=false&reload=true`,
"webpack/hot/only-dev-server",
`${srcPath}/index.tsx`,
]
This is my middleware
const compiler = webpack(config);
const server = express();
server.use(
DevMiddleware(compiler, {
publicPath: config.output!.publicPath!,
}),
);
server.use(
HotMiddleware(compiler, {
path: `/${proxied_path}/webpack_hot`,
heartbeat: 1000,
}),
);
Try to hoist component, there might an error with it, as long as it's not a top level variable.
function App() {
// + const [_0] = useState(0);
useEffect(() => {
console.log("app first render");
return () => {
console.log("app will unmount");
};
}, []);
useEffect(() => {
console.log("app updated");
return () => {
console.log("app before update");
};
});
return <>App</>;
});
export default hot(React.memo(App));
wait a moment... hook reloading is relaying on babel plugin. Without it, they would behave exactly as in your example.
You have to use babel, however it might apply only RHL plugin, keeping TS transformation for ts-loader
emmm okey. I don't read the doc carefully to know I have to use babel...
This issue can be closed.