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

React 18 does not live reload with Shadow-CLJS in non-trivial projects #579

Open
filipesilva opened this issue Sep 7, 2022 · 5 comments

Comments

@filipesilva
Copy link

Using Reagent+React18+Shadow-CLJS will not live reload unless if the file changed is a direct dependency of the file containing the render code.

I have a repro that illustrates this behaviour:

git clone https://github.com/filipesilva/react18-rerender
cd react18-rerender
yarn
yarn start

Open http://localhost:3001 in your browser and you should see the following:

comp1
comp2
comp3

The browser console will show the following:

render comp1
render comp2
render comp3

Each component is on a different file, app.core/main will render comp1, comp1 will render comp2, and comp2 will render comp3. Each comp will print to the console when rendered. A render fn has the ^:dev/after-load metadata that causes Shadow-CLJS to call it after code changes.

If you edit comp1 or comp2 (e.g. add another number to the string), live reload will work. If you edit comp3, it will not.

As far as I can tell, the core reason is that the new React 18 rendering fn keeps some state, and will not render the root element unless it changed. In React <17, I think it always rerendered when .render was called.

Specific to Shadow-CLJS is that it will reload the changed file and all files that directly depend on it, then call the after-load fn. You can see logs for this in the console when changing comp3:

shadow-cljs: load JS app/comp3.cljs
shadow-cljs: load JS app/comp2.cljs
shadow-cljs: call app.core/render

Note that the render compX logs never appeared. In contrast, when editing comp2:

shadow-cljs: load JS app/comp2.cljs
shadow-cljs: load JS app/comp1.cljs
shadow-cljs: call app.core/render
render comp1
render comp2
render comp3

So far I've found two workarounds for this:

  1. Render a comp with an anonymous fn (which always changes identity) that returns the comp you really want at root: (.render root (r/as-element [(fn [] comp1/main)]))
  2. Mark the ns of the comp you render at root with ^:dev/always, which causes it to always be reloaded when any file changes.

Unsure if there's any better ways.

filipesilva added a commit to athensresearch/athens that referenced this issue Sep 7, 2022
@flexsurfer
Copy link

hey @filipesilva does your project work fine with React18? any issues except live reloading? thanks

@filipesilva
Copy link
Author

@flexsurfer we had some trouble with other third party js lib and ended up going back to 17. It seemed like reagent was fine with it though.

@flexsurfer
Copy link

flexsurfer commented Jan 16, 2023

hey @Deraen , tested latest master , hot reload works fine, any chance we could have a snapshot or release on clojars? thanks

@zalky
Copy link

zalky commented Jan 18, 2023

I've been testing my library with React 18, and tried the new create-root way of rendering a root node, but it seems to break hot reloading in a way similar to what is described in this issue. This is using the latest master (e67d4f8) branch of Reagent.

Both of @filipesilva's workarounds appear to partially mitigate the issue. But I'm not exactly sure that it is specific to React 18. When using master (e67d4f8), the old rendering approach with React 17 now also seems to have hot loading issues. Version 1.1.1 of Reagent seems to be fine.

Interestingly, if I revert commit 9211080 on the master branch, this resolves hot reloading with the old approach for both React 17 and React 18. Of course using the old approach with React 18 will produce the expected warnings and most of the new React 18 features will not be available.

@zalky
Copy link

zalky commented Jan 18, 2023

Wrapping the call to react-dom/render on L35 of reagent.dom seems to fix the old approach:

                 (binding [util/*always-update* true]
                   (react-dom/render
                       (react/createElement reagent-root #js {:callback callback
                                                              :comp comp})
                       container))

But I still can't get the new create-root approach to hot reload without the workarounds suggested above.

zalky added a commit to zalky/reflet that referenced this issue Jan 19, 2023
There are still a lot of gotchas with Reagent + React 18.

Specifically, see:

reagent-project/reagent#579

Without the workaround described in that issue, root React nodes, like
the debugger overlay don't hot reload properly.
zalky added a commit to zalky/reflet that referenced this issue Jan 19, 2023
There are still a lot of gotchas with Reagent + React 18.

Specifically, see:

reagent-project/reagent#579

Without the workaround described in that issue, root React nodes, like
the debugger overlay don't hot reload properly.
zalky added a commit to zalky/reflet that referenced this issue Jan 19, 2023
There are still a lot of gotchas with Reagent + React 18.

Specifically, see:

reagent-project/reagent#579

Without the workaround described in that issue, root React nodes, like
the debugger overlay don't hot reload properly.
zalky added a commit to zalky/reflet that referenced this issue Jan 19, 2023
There are still a lot of gotchas with Reagent + React 18.

Specifically, see:

reagent-project/reagent#579

Without the workaround described in that issue, root React nodes, like
the debugger overlay don't hot reload properly.
zalky added a commit to zalky/reflet that referenced this issue Jan 31, 2023
There are still a lot of gotchas with Reagent + React 18.

Specifically, see:

reagent-project/reagent#579

Without the workaround described in that issue, root React nodes, like
the debugger overlay don't hot reload properly.
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

3 participants