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

Feedback wanted: New Hot Reloading #7227

Open
gaearon opened this issue Jun 15, 2019 · 30 comments

Comments

Projects
None yet
@gaearon
Copy link
Member

commented Jun 15, 2019

I’m working on hot reloading again. Got a very raw alpha version working. It preserves state but only for function components. Works with Hooks.

You can try the alpha version (not production ready, super experimental):

Trying in a New Project (NOT FOR PRODUCTION)

npx create-react-app demo --scripts-version wonky-scripts

Trying in an Existing Project (NOT FOR PRODUCTION)

  1. Replace react-scripts dependency with wonky-scripts@0.0.5
  2. Keep scripts the same
  3. Delete node_modules/.cache
  4. Run Yarn/npm
  5. Start the project and try editing your React components

What It Looks Like

It’s expected that it will work something like on this gif: https://twitter.com/dan_abramov/status/1139876172903395329

Constraints (Library Authors, Read This!)

If your Hook or Component doesn't work with hot reload, keep in mind that:

  • useMemo and useCallback caches are dropped on every edit (otherwise there wouldn't be a way to edit them 😅). If this breaks your code, consider useRef which gives you a semantics guarantee about not getting re-created. Like here. Usually there's a way to restructure the code to be more resilient.
  • Same goes for useEffect. During hot reload, dependency array will be ignored, and even effects with [] dependencies will re-run. If this breaks your component or Hook, there's likely a way to restructure it to fix this. As a bonus, this will make it easier for you to later add more dependencies to it if needed.
  • However, state and refs get preserved between edits. (As an escape hatch for quickly editing mounting animations and similar, note that users can add // @hot reset to the file they're editing, and this will force state reset. This is not a final syntax but we'll document some way to do it.)

If you need help getting your library working, please post in this thread.

Known issues

  • Hot reload gets stuck if you save a file without changing it
  • Editing a file that declares Context doesn't preserve state, currently you need to move Context definition to another module and import it
  • Errors after hot reload don't always get reported (e.g. try importing a non-existent component and then adding a file without exports)
  • Lint warnings are confusingly duplicated on save
  • Some libraries don't work with it (please post which ones in this thread)

Please Share Feedback!

In this thread I’d love to hear first feedback from the brave folks who are willing to try this version on their projects. (Remember: it’s NOT usable in production, it’s just an experiment. This is why it has a funny name.)

Does it work for you? Can you make a gif of how it feels in your app, assuming it’s not a secret?

Thanks!

@ar1a

This comment has been minimized.

Copy link

commented Jun 15, 2019

Works great, but when changing inside a form from react-hook-form, it dropped the state. It doesn't seem to do this with unmanaged inputs specifically, so it seems like a library collision or something.

Here is a link to the file I was testing with, if you can't recreate it with a basic setup

Here is a webm of it happening

EDIT: After rendering the exact same component with hooks in a separate project, i can't get it to reproduce. I think it has something to do with the components wrapping it. Maybe contextapi? The quest continues...

@gaearon

This comment has been minimized.

Copy link
Member Author

commented Jun 15, 2019

Thanks. Any chance you can get a minimal reproducing project up so I can look closer at why it loses state?

@ar1a

This comment has been minimized.

Copy link

commented Jun 15, 2019

import React, { useContext } from 'react';

const App: React.FC = () => {
  return (
    <form>
      {/* Change component here */}
      <input name="content" />
    </form>
  );
};

const ExampleContext = React.createContext(5);

const Feed = () => {
  const ctx = useContext(ExampleContext);
  return <App />;
};

const WrappedApp = () => (
  <ExampleContext.Provider value={5}>
    <Feed />
  </ExampleContext.Provider>
);

export default WrappedApp;

It has to do with the contexts! not react-hook-form at all.

Webm of it happening with this example!

@gaearon

This comment has been minimized.

Copy link
Member Author

commented Jun 15, 2019

Oh yeah — for now you’d have to move context definition into a separate file (and import it from the component). That should work.

@gaearon

This comment has been minimized.

Copy link
Member Author

commented Jun 15, 2019

(I do have a version without this limitation but it’s a bit more invasive so I left it out.)

@bugzpodder

This comment has been minimized.

Copy link
Collaborator

commented Jun 15, 2019

[EDIT] I removed .npmrc and it worked after that.

For some reason I am ahving trouble pulling wonky scripts:

@@ -67,7 +67,7 @@
-    "react-scripts": "^3.0.1",
+    "wonky-scripts": "0.0.5",
info There appears to be trouble with your network connection. Retrying...
error Couldn't find package "wonky-scripts@0.0.5" required by `client`  on the "npm" registry.

revert replacing wonky-scripts with react-scripts and yarn has no issues..

Also tried with a tiny app and npm, can't get it work either.

[EDIT] I removed .npmrc and it worked after that.

@le-du6

This comment has been minimized.

Copy link

commented Jun 15, 2019

It works perfectly especially with useEffect ;-)
Many Thanks 👏🏻

wonky-scripts

@bugzpodder

This comment has been minimized.

Copy link
Collaborator

commented Jun 15, 2019

Ran into an issue hot.js:167 Uncaught TypeError: findHostNodesForHotUpdate is not a function

@gaearon

This comment has been minimized.

Copy link
Member Author

commented Jun 15, 2019

@bugzpodder It is supposed to be there if you use the ReactDOM that this package internally aliases. So this sounds strange.

@niwsa

This comment has been minimized.

Copy link

commented Jun 15, 2019

hr-hooks
Shouldn't the bottom Hooked instance maintain its state ?

EDIT: seems like this is the expected behaviour as react sees a different tree in place of Hooked (replaced with div) hence it unmounts the existing component.If thats the case this is a non issue.

@gaearon

This comment has been minimized.

Copy link
Member Author

commented Jun 15, 2019

seems like this is the expected behaviour as react sees a different tree in place of Hooked (replaced with div) hence it unmounts the existing component.If thats the case this is a non issue.

Yeah, that's the reason. Not sure there's anything we can do for that case.

@mlshv

This comment has been minimized.

Copy link

commented Jun 16, 2019

This is a super cool feature, I’m really excited!

Will it be possible to set it up without CRA in a raw webpack setup?

@thetrompf

This comment has been minimized.

Copy link

commented Jun 16, 2019

@niwsa what happens if you explicitly set the key prop on the Hooked elements?

@niwsa

This comment has been minimized.

Copy link

commented Jun 16, 2019

@thetrompf setting a stable key worked,the instance state was preserved...

ar1a added a commit to ar1a/Catter that referenced this issue Jun 16, 2019

@soufDev

This comment has been minimized.

Copy link
Contributor

commented Jun 16, 2019

@gaearon still working for me, like the gif in the tweet mentioned above

@niwsa

This comment has been minimized.

Copy link

commented Jun 16, 2019

@gaearon Adding a side effect (useEffect) on the fly resets the state.Is that expected ?

@gaearon

This comment has been minimized.

Copy link
Member Author

commented Jun 16, 2019

Adding a side effect (useEffect) on the fly resets the state.Is that expected ?

Yeah. Any change to call order will reset the state. We could in theory supporting adding Hooks at the end without resetting the state but it doesn't seem super important right now.

Additionally, it's expected that effects will always reset on every edit, even with []. This is intentional. If it breaks your effects you might wanna rethink how they're structured. Since it also makes it difficult for you to add new dependencies to them when needed.

@gaearon

This comment has been minimized.

Copy link
Member Author

commented Jun 16, 2019

Will it be possible to set it up without CRA in a raw webpack setup?

Yes, with some work.

@gaearon

This comment has been minimized.

Copy link
Member Author

commented Jun 16, 2019

I noticed a bug: it gets "stuck" if you save a file without actually editing it. 😛 Will need to look into this closer to an actual release.

@niwsa

This comment has been minimized.

Copy link

commented Jun 16, 2019

Reading the documentation for hooks the first time and trying out the examples in that .. I may raise some false alarms with regard to hot reloading 😄 ... If you have some pointers, as to what to watch out for it would be great.
UPDATE Just saw the known issues update now :)

@gaearon

This comment has been minimized.

Copy link
Member Author

commented Jun 16, 2019

I added some info in the original post about constraints. Hope this is helpful for library authors.

@adamkleingit

This comment has been minimized.

Copy link

commented Jun 18, 2019

Couldn't make it work with CRA wonky-scripts:

yarn run v1.15.2
warning ../../package.json: No license field
$ react-scripts start

There might be a problem with the project dependency tree.
It is likely not a bug in Create React App, but something you need to fix locally.

The wonky-scripts package provided by Create React App requires a dependency:

  "jest": "24.7.1"

Don't try to install it manually: your package manager does it automatically.
However, a different version of jest was detected higher up in the tree:

  /Users/adamklein/projects/reusable/node_modules/jest (version: 24.8.0) 

Manually installing incompatible versions is known to cause hard-to-debug issues.

If you would prefer to ignore this check, add SKIP_PREFLIGHT_CHECK=true to an .env file in your project.
That will permanently disable this message but you might encounter other issues.

To fix the dependency tree, try following the steps below in the exact order:

  1. Delete package-lock.json (not package.json!) and/or yarn.lock in your project folder.
  2. Delete node_modules in your project folder.
  3. Remove "jest" from dependencies and/or devDependencies in the package.json file in your project folder.
  4. Run npm install or yarn, depending on the package manager you use.

In most cases, this should be enough to fix the problem.
If this has not helped, there are a few other things you can try:

  5. If you used npm, install yarn (http://yarnpkg.com/) and repeat the above steps with it instead.
     This may help because npm has known issues with package hoisting which may get resolved in future versions.

  6. Check if /Users/adamklein/projects/reusable/node_modules/jest is outside your project directory.
     For example, you might have accidentally installed something in your home folder.

  7. Try running npm ls jest in your project folder.
     This will tell you which other package (apart from the expected wonky-scripts) installed jest.

If nothing else helps, add SKIP_PREFLIGHT_CHECK=true to an .env file in your project.
That would permanently disable this preflight check in case you want to proceed anyway.

P.S. We know this message is long but please read the steps above :-) We hope you find them helpful!

error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
@adamkleingit

This comment has been minimized.

Copy link

commented Jun 18, 2019

SKIP_PREFLIGHT_CHECK=true worked though

Couldn't make it work with CRA wonky-scripts:

yarn run v1.15.2
warning ../../package.json: No license field
$ react-scripts start

There might be a problem with the project dependency tree.
It is likely not a bug in Create React App, but something you need to fix locally.

The wonky-scripts package provided by Create React App requires a dependency:

  "jest": "24.7.1"

Don't try to install it manually: your package manager does it automatically.
However, a different version of jest was detected higher up in the tree:

  /Users/adamklein/projects/reusable/node_modules/jest (version: 24.8.0) 

Manually installing incompatible versions is known to cause hard-to-debug issues.

If you would prefer to ignore this check, add SKIP_PREFLIGHT_CHECK=true to an .env file in your project.
That will permanently disable this message but you might encounter other issues.

To fix the dependency tree, try following the steps below in the exact order:

  1. Delete package-lock.json (not package.json!) and/or yarn.lock in your project folder.
  2. Delete node_modules in your project folder.
  3. Remove "jest" from dependencies and/or devDependencies in the package.json file in your project folder.
  4. Run npm install or yarn, depending on the package manager you use.

In most cases, this should be enough to fix the problem.
If this has not helped, there are a few other things you can try:

  5. If you used npm, install yarn (http://yarnpkg.com/) and repeat the above steps with it instead.
     This may help because npm has known issues with package hoisting which may get resolved in future versions.

  6. Check if /Users/adamklein/projects/reusable/node_modules/jest is outside your project directory.
     For example, you might have accidentally installed something in your home folder.

  7. Try running npm ls jest in your project folder.
     This will tell you which other package (apart from the expected wonky-scripts) installed jest.

If nothing else helps, add SKIP_PREFLIGHT_CHECK=true to an .env file in your project.
That would permanently disable this preflight check in case you want to proceed anyway.

P.S. We know this message is long but please read the steps above :-) We hope you find them helpful!

error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
@hmeerlo

This comment has been minimized.

Copy link

commented Jun 20, 2019

Ok, sorry but I have no reproducable scenario because I switched back after a day of trying it out. The biggest problem for me was that the build used to fail on typescript errors and it no longer did that.

@gaearon

This comment has been minimized.

Copy link
Member Author

commented Jun 20, 2019

More concrete information than “fail” would be really helpful. Fail how?

(I haven’t really tried it with TypeScript so not sure what kind of issues it might run into.)

@hmeerlo

This comment has been minimized.

Copy link

commented Jun 20, 2019

yeah sorry I totally agree. With react-scripts 3.0.0 my build fails in the terminal whenever I have a typescript error. I run the terminal in my IDE, so I immediately see it and fix the error (even though the IDE points me to the errors as well). But with the wonky-scripts it no longer fails the build in the terminal. It does show the typescript warning though. So I constantly assumed my IDE was wrong with the typescript errors, where it was actually right and the build just didn't show them anymore.

@TonyMasterR

This comment has been minimized.

Copy link

commented Jun 22, 2019

Does it require the use of create react app or I can just add it to existing package.json and use ?

@mrmckeb

This comment has been minimized.

Copy link
Collaborator

commented Jun 23, 2019

This is great, very exciting. I know a lot of people will love this.

For clarity, I understand that classes will not be supported by this work, even once completed. Is that correct?

@theKashey

This comment has been minimized.

Copy link

commented Jun 24, 2019

For clarity, I understand that classes will not be supported by this work, even once completed. Is that correct?

Class-based components would be recreated, preserving the underlaying tree, but not the component itself.

@SurenAt93

This comment has been minimized.

Copy link

commented Jun 25, 2019

example

I tested it on this library, it seems like everything is working as expected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.