gaearon / react-hot-loader

Tweak React components in real time. (Deprecated: use Fast Refresh instead.)
http://gaearon.github.io/react-hot-loader/
MIT License
12.26k stars 801 forks source link

It doesn't work with React.lazy #1425

Open rainydayDY opened 4 years ago

rainydayDY commented 4 years ago

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: when I user React.lazy, it doesn't work

Expected behavior

What you think should happen: state can remain

Actual behavior

What actually happens: state can't remain

Environment

React Hot Loader version: 4.12.19 "devDependencies": { "@babel/core": "^7.8.3", "@babel/plugin-proposal-class-properties": "^7.8.3", "@babel/plugin-proposal-decorators": "^7.8.3", "@babel/plugin-transform-runtime": "^7.8.3", "@babel/preset-env": "^7.8.3", "@babel/preset-react": "^7.8.3", "babel-loader": "^8.0.6", "express": "^4.17.1", "html-webpack-plugin": "^3.2.0", "webpack": "^4.41.5", "webpack-cli": "^3.3.10", "webpack-dev-middleware": "^3.7.2", "webpack-dev-server": "^3.10.3", "webpack-hot-middleware": "^2.25.0" }, "dependencies": { "@babel/runtime-corejs3": "^7.8.3", "connected-react-router": "^6.7.0", "history": "^4.10.1", "prop-types": "^15.7.2", "react": "^16.12.0", "react-dom": "^16.12.0", "react-hot-loader": "^4.12.19", "react-redux": "^7.1.3", "react-router-dom": "^5.1.2", "redux": "^4.0.5", "redux-thunk": "^2.3.0" }

Run these commands in the project folder and fill in their results:

  1. node -v: v12.15.0
  2. npm -v: 6.13.4

Then, specify:

  1. Operating system: mac os
  2. Browser and version: chrome

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.

you can use my project and reappear it : https://github.com/rainydayDY/webpack-fe

theKashey commented 4 years ago

Your example is too big. I've just checked this example and it works perfectly.

However there are two "modes" RHL can handle lazy with. Please try another one. See Out-of-bound warning

If the tail update detection is not something you want or need, you can disable this behaviour by setting setConfig({ trackTailUpdates:false }).

By disabling trackTailUpdates you will activate another mode with a bit more aggressive lazy management.

xyy94813 commented 4 years ago

@theKashey how to run the example ??

I run the newest example with error in browser:

Uncaught TypeError: realPolyfill is not a function
    at eval (react-hot-loader.development.js:1379)
    at Object../node_modules/react-hot-loader/dist/react-hot-loader.development.js (bundle.js:1676)
    at __webpack_require__ (bundle.js:725)
    at fn (bundle.js:102)
    at eval (index.js:19)
    at Object../node_modules/react-hot-loader/index.js (bundle.js:1700)
    at __webpack_require__ (bundle.js:725)
    at fn (bundle.js:102)
    at eval (react-lifecycles-compat.es.js:8)
    at Object.eval (react-lifecycles-compat.es.js:10)
xyy94813 commented 4 years ago

Someone say it maybe @hot-loader/react-dom problem. https://github.com/hot-loader/react-dom/issues/8#issuecomment-620611639

But, It is not work for me without using @hot-loader/react-dom.

I found a interesting thins when i debugger:

  1. Change a lazy load component.
  2. HotLoaderClient will receive a WS msg success.
  3. And react-hot-loader will target update function; The root component forceUpdate()
  4. log warn: React-Hot-Loader: some components were updated out-of-bound. Updating your app to reconcile the changes.
  5. lazy load component re-render
  6. Nothing change in page.

https://github.com/gaearon/react-hot-loader/blob/5e226f40aea2f995adbb446199a9cb93656ef465/src/hot.dev.js#L54-L82

If i wrap lazy load component by hot, `module, everything work well.

There are some question:

theKashey commented 4 years ago

Found a problem in tailUpdate - any pure/memo component could stop this "secondary" update. So if your application is good written - you will experience this problem, but only if react-dom patch is not enabled.

I don't have a "broken" example I am able to fix, so, @xyy94813 - could you try to use this version of hot.dev.js, and check is it helping in your case or not - https://github.com/gaearon/react-hot-loader/blob/b14f49b085a6b48b8eeadeeb1a4bf25c981dc71c/src/hot.dev.js

https://github.com/gaearon/react-hot-loader/pull/1448/files#diff-eb1f44974215c23befb11f74f6a2d4d4

xyy94813 commented 4 years ago

@theKashey

This version work well for me,even i set trackTailUpdates to false.

Is it a excepted?

xyy94813 commented 4 years ago

@theKashey

Well... Looks like it has side effects

Each child node in the chunk will be re-mounted again.

I'm not sure what is your expectation.

theKashey commented 4 years ago

The changes I've made could not cause remount. They were just about a bit more deeper updates.

xyy94813 commented 4 years ago

I am stuck in confusion...

I write a minimized implementation...

Everything work well with react-hot-loader@4.12.20... PS: lazy-component will be re-mount too...

xuya227939 commented 4 years ago

I have also encountered the same problem,How can I solve it, for example?

X-neuron commented 4 years ago

webpack.dev.config.js:

resolve: {
    extensions: ['.ts', '.tsx', '.js', '.jsx'],
    alias: {
      "@": path.resolve(__dirname, 'src'),
      // 'react-dom': '@hot-loader/react-dom',  //delete this line
    }
  },
{
            loader: 'babel-loader',
            options: {
              cacheDirectory: true,
              // See #6846 for context on why cacheCompression is disabled
              cacheCompression: false,
              presets: ['@babel/preset-env'],
              plugins: [
                'lodash',
                // 'react-hot-loader/babel',  // delete this line
                // '@babel/plugin-proposal-object-rest-spread',
              ]
            },
          },

in app.jsx : just use export default hot(App); it will work fine in code spliting condition

X-neuron commented 4 years ago

I have also encountered the same problem,How can I solve it, for example?

https://github.com/X-neuron/antdFront.git this is good example for hot reload in code split condition

linshuizhaoying commented 4 years ago

I have also encountered the same problem,How can I solve it, for example?

https://github.com/X-neuron/antdFront.git this is good example for hot reload in code split condition

I can't believe the official configuration caused the error, but it exist...

xyy94813 commented 4 years ago

I am using react-refresh with react-refresh-webpack-plugin. It work well with lazy-component.

This plugin has been integrated into CRA. It looks like it will be released with CRA V4.

react-hot-loader will be deprecated... https://github.com/gaearon/react-hot-loader/issues/1453

theKashey commented 4 years ago

It's already

monochrome-yeh commented 4 years ago

I am using react-refresh with react-refresh-webpack-plugin. It work well with lazy-component.

This plugin has been integrated into CRA. It looks like it will be released with CRA V4.

react-hot-loader will be deprecated...

1453

How did you solve this issue, I’m using cra4.0 (react17.0.1) with react-refresh and we pack plug-in, it still could not be able to handle hot reload with react.lazy component.