Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error in [email protected] after upgrade react 16 #643

Closed
mymtw opened this issue Sep 26, 2017 · 15 comments
Closed

Error in [email protected] after upgrade react 16 #643

mymtw opened this issue Sep 26, 2017 · 15 comments

Comments

@mymtw
Copy link

mymtw commented Sep 26, 2017

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

ERROR in ./src/client/containers/App/index.js
Module not found: Error: Can't resolve 'react/lib/ReactMount' in '/Users/apple/blahblahblag/src/client/containers/App'
@ ./src/client/containers/App/index.js 1:304-335
@ ./src/client/routes.jsx
@ ./src/client/index.js
@ multi (webpack)-dev-server/client?http://0.0.0.0:8050 webpack/hot/dev-server babel-polyfill ./src/client/index.js

What you are reporting:
Error

Expected behavior

What you think should happen:
I've just updated before react v16, this wasn't earlier

What actually happens:
error

Environment

  "dependencies": {
    "babel-plugin-transform-decorators-legacy": "^1.3.4",
    "babel-polyfill": "^6.26.0",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-0": "^6.24.1",
    "bluebird": "^3.5.0",
    "body-parser": "^1.18.1",
    "classnames": "^2.2.5",
    "cookie-parser": "~1.4.3",
    "debug": "^3.0.1",
    "express": "^4.15.4",
    "isomorphic-fetch": "^2.2.1",
    "moment": "^2.18.1",
    "morgan": "^1.8.2",
    "nunjucks": "^3.0.1",
    "octicons": "^6.0.1",
    "prop-types": "^15.5.10",
    "react": "^16.0.0",
    "react-bootstrap": "^0.31.3",
    "react-helmet": "^5.2.0",
    "react-md-spinner": "^0.2.5",
    "react-recaptcha": "^2.3.5",
    "react-redux": "^5.0.6",
    "react-router": "3.2.0",
    "react-router-bootstrap": "^0.23.3",
    "react-toggle-switch": "^3.0.3",
    "redux": "^3.7.2",
    "redux-logger": "^3.0.6",
    "redux-thunk": "^2.2.0",
    "serve-favicon": "^2.4.4",
    "universal-cookie": "^2.1.0"
  },
  "devDependencies": {
    "assets-webpack-plugin": "^3.5.1",
    "babel-core": "^6.26.0",
    "babel-eslint": "^7.2.3",
    "babel-loader": "^7.1.2",
    "babel-plugin-react-transform": "^3.0.0",
    "clean-webpack-plugin": "^0.1.17",
    "compression-webpack-plugin": "^1.0.0",
    "css-hot-loader": "^1.3.1",
    "css-loader": "^0.28.7",
    "css-modules-require-hook": "^4.2.2",
    "enzyme": "^3.0.0",
    "eslint": "^4.5.0",
    "eslint-loader": "^1.9.0",
    "eslint-plugin-react": "^7.3.0",
    "extract-text-webpack-plugin": "^3.0.0",
    "file-loader": "^0.11.2",
    "jest": "^21.0.1",
    "nodemon": "^1.12.1",
    "npm-run-all": "^4.1.1",
    "postcss": "^6.0.11",
    "react-dom": "^16.0.0",
    "react-hot-loader": "^1.3.1",
    "react-test-renderer": "^16.0.0",
    "style-loader": "^0.18.2",
    "url-loader": "^0.5.9",
    "webpack": "^3.6.0",
    "webpack-bundle-size-analyzer": "^2.7.0",
    "webpack-dev-server": "^2.8.2"
  }

React Hot Loader version:
"react-hot-loader": "^1.3.1",
Run these commands in the project folder and fill in their results:

  1. node -v:
  2. npm -v:

Then, specify:

  1. v7.2.1
  2. 5.4.2
  3. Operating system:
    macos
  4. Browser and version:
    chrome latest

Reproducible Demo

@mymtw mymtw changed the title Error 1.3.1 after upgrade react 16 Error in [email protected] after upgrade react 16 Sep 26, 2017
@Dwlad90
Copy link

Dwlad90 commented Sep 26, 2017

+1

@gregberge
Copy link
Collaborator

It uses React internals no longer exposed in React 16, I have to check how to do it now with @gaearon.

@gaearon
Copy link
Owner

gaearon commented Sep 27, 2017

Yes, these internals don't exist anymore. 1.x will not work with React 16.

Please try to see if 3.x works for you. If it doesn't file issues.

Now that we have a new core I think we can take another look at what needs to be exposed for hot reloading.

@gaearon gaearon closed this as completed Sep 27, 2017
@mymtw
Copy link
Author

mymtw commented Sep 27, 2017

@gaearon 3.x still in beta, I didn't want to use it

@gaearon
Copy link
Owner

gaearon commented Sep 27, 2017

The "beta" label there just means that nobody found time to do the job of updating docs etc. 3.x is much more stable than 1.x ever was.

@noahgrant
Copy link

hi @gaearon (love your work and thank you!), i actually don't want to upgrade to 3.x because it requires so many other changes to our codebase (for example, figuring out how to appropriately adding module.hot blocks to our code splits (we don't use React Router), the fact that we use decorators exclusively in the way that doesn't work with RHL, etc etc). we have been thrilled with 1.x, but would also like to upgrade to react 16; the problem is that not having a RHL on-par with react 15 would be a blocker for upgrading because of RHL's incredible productivity benefits.

that said, i'd happily fork 1.x and make minor modifications if that were all that was necessary to fix the ReactMount issues. if you might be able to point me in the right direction or give any tips, that would be greatly appreciated. thank you!

@theKashey
Copy link
Collaborator

@noahgrant - I am currently on duty and I still have a hope that we could solve problems with decorators, compositions and other stuff RHL cant, but should handle.

Handle code splitting is also not a great problem, but it depends on the loader you use. Popular repos does not support RHL, but it is possible to fix it:

  1. Dont user loaders, which does not react on componentWillReceiveProps( loadable-components, react-loadable ), or you will never even fetch update from a server, as long they do it onComponentWillMount (eaten by RHL).
  2. Wrap rendered component in RHL's Application, to get them re-rendered after code update.

It is hard to make a good advice which loader you should use, as long the best ones were just named as "not usable". I know only 2 loaders with good hot behavior.

The good part: the interface is always almost same.

@noahgrant
Copy link

thanks @theKashey, but i'm not actually looking to upend my existing infrastructure to support different tools. my issue is really that i can't keep using RHL 1.3 when upgrading to react, and, tbh, our existing 1.3 usage is the smoothest dev experience. if there's a way that i can easily replace the mounting function (./lib/Mount) with something for react 16, that would be really wonderful. if it's not too involved, i can try to take that on myself.

upgrading to RHL 3.x, i'm seeing all kinds of odd behavior, like updates navigating back to a previous SPA route, component proxies copying over components but leaving their props as undefined (which then errors), and updating in place once but then reloading on additional updates. in general, 1.3x is such a better dev experience that i'm not sure we can update to react 16 without it. is there another exposed internal from React 16 that can replace lib/Mount?

thank you for your time!

@theKashey
Copy link
Collaborator

Thats the difference between v1 and v3?

  • v1 adds module.accept to the end of each file with React.Component inside, hooks the exports and do its work. Working from the bottom, and for a single file.
    As result if you change a single file - only single file will be updated. As result - if you have decorators somewhere higher - they will be just NOT re-rendered. And, as result, deferred loaders are works.

  • v3 asks you to add module.accept to the application mount point. It works from top to bottom. And if you will change a single file - a whole subtree will be updated. Thats why you can get whole tree rerender and will face some problems with code splitting.

Behavior of v1 is very, very bad.

  • First of all - it does not support Stateless Functional Components. As long any function could be SFC - it justs ignores the at all.
  • Second - it adds appends module by self-accept code. Not all files could be self accepted.

So, if you want V3 to behave as V1 - just append each file with this code from V1. But you could not append each file. It is not a good idea.

@noahgrant
Copy link

i think we might be misunderstanding each other a bit. v3 is unusable for me right now for a few reasons—one is the binding issue after transpiling only to modern browsers. but another reason is simply that our app architecture doesn't easily work with the things v3 requires:

  1. we depend on shouldComponentUpdate when we update pages (we don't use React Router) to show a loader over the previous page. this isn't possible when our top component is rendered as children (where no diff/sCU happens, in this case via AppContainer).

  2. we use require.ensure for code splitting, and while i have gotten it to work a little bit with webpack HMR, it has caused some issues with hot reloader.

not to mention i'm just getting very inconsistent behavior from reloading, like when it hot reloads once and then refreshes on the next save. so, now back to your other point:

Behavior of v1 is very, very bad.

this is not my experience—in fact, relative to the issues i highlighted above, i will gladly take any of v1's shortcomings. v3 is impossible to use right now, and v1 seems to fail only because it doesn't know how to mount in react 16. if there is a modestly easy way to plug in a ReactMount equivalent to v1, i would much, much rather do that, since there are mega issues with v3 (at least, it seems, when not using a fairly strict architecture), and it also seems like there isn't much development on it (some of those major open issues have been open for over a year).

so, given this, how can we replace ReactMount in v1?

thank you again for your time!

@theKashey
Copy link
Collaborator

Forget about V1. It is easier to make V3 working as V1 that to keep it alive.
How to do it:

  1. copy webpack/index.js from this repo
  2. modify it, to contain code from V1
if(typeof React !== 'undefined'){
    // self accept all `react` modules
   module.hot.accept(function(){}); 
   module.exports.forEach( module => {
      if(typeof module==='function'){
        try{
          React.createElement(module); // this triggers react-proxy
        }catch(e){}
     }
 });
// code is not tested

PS: And next you somehow have to trigger deepForceUpdate. But you stop HRM even bubbling and Application will not receive it. And you dont have access to mounted instanced - react-proxy does not expose it. Maybe there is some webpack API for it...
3. You just converted V1 to behave as V1. And it will work with React 16.

If one good day one good one will create babel rules to detect possibilities of safe-self-accepted of a module - it will change the game rules. But for now, it is too dangerous.

PS: v3 is unusable for me right now for a few reasons—one is the binding issue after transpiling only to modern browsers.
We already have a solution in dev branch.

@noahgrant
Copy link

thanks, @theKashey. to be honest, i'm not sure i understood the statements that were written in your PS above, but unless i can use v3 with un-transpiled es6, it doesn't matter. i'll try to work on it at some point. in the meantime, i think i'll have to stay on React v15...

@theKashey
Copy link
Collaborator

Same shit :)

@mymtw
Copy link
Author

mymtw commented Nov 30, 2017

Currently It looks like further development of React 16 is meaningless, while his ecosysyem not ready to use him

@theKashey theKashey mentioned this issue Dec 4, 2017
10 tasks
@noahgrant
Copy link

noahgrant commented Dec 6, 2017

For posterity, I ended up really hacking together a solution to use v1 with React 16.

  1. I forked the RHL repo and removed all ReactMount references.
  2. In my app logic, I exposed my root component to the global scope:
if (process.env.NODE_ENV !== 'production') {
  window.rootComponent = myRootComponent;
}
  1. in RHL v1's index.js, require in react-deep-force-update v1 here
  2. in RHL v1's index.js, replace this line with:
'deepForceUpdate(React)(window.rootComponent);',

This isn't optimal, of course, but has allowed us to maintain the productivity benefits of RHL (v1) while also being able to upgrade to React 16. Just wanted to post here in case other people are having the same problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants