Reagent 2.0 is now out: https://github.com/reagent-project/reagent/blob/master/CHANGELOG.md#200-2025-10-29
Tried upgrading from Reagent 17 to all the new and shiny versions of everything.
At least two things broke in a quite complex project:
• Some things aren't rendered at first, any code change that triggers a re-render immediately fixes it. Not sure what it's about yet
• Popovers in an old and heavily modified fork of re-com stopped showing up. The popovers rely on toggling a boolean ratom inside :component-did-mount and deref'ing it in :reagent-render, so that it's rendered twice - once off-screen for geometry and the second and final pass for proper positioning based on that geometry. For some reason, re-render doesn't happen when the ratom is toggled. Tried the demo website of the most recent re-com version with Reagent 2 and React 19 - it worked perfectly. But there are a lot of differences between what I have and what the newer re-com has so can't quickly tell what's going on.
If anyone else has a similar experience, it could be useful to know whether there were any interesting findings.
re-com used to use dom-node like two years ago, if your fork is even older than that, that would be once place that might break stuff
should show a compilation error about a missing function though in that case
I got rid of dom-node in my fork quite some time ago.
I think my next step is to create an MRE because no idea how to debug it otherwise.
@p-himik hmm this might be a real bug in Reagent. Looks like the same issue as function components had, mount->unmount->mount, the reagent render ratom (which follows the deref in render fn) is disposed and not restored
Oh! Well, good thing I caught it early-ish. :D
Not sure if I would recommend using StrictMode with Reagent anyway, but best to try to ensure it works
If it is the same problem, the same fix should work
I don't know if it is or can be relevant in any way, but just recently I learned that during development the useEffect hook calls its body twice when the dependencies are an empty array. Apparently, without StrictMode.
Seems that it could potentially be relevant if useEffect deals with ratoms.
https://github.com/reagent-project/reagent/pull/647/files I'll add a test and maybe clean the code a bit now that the same code is used for both class and fn components
@p-himik can you test with the latest commit from the branch? I got the test case also working. After wondering for a while why it didn't happen, but I was on React 18 and the with-render test util didn't support StrictMode for that case. But now tested with React 18 also, and problem did exist there also.
Everything seems to work! This also got fixed: "Some things aren't rendered at first, any code change that triggers a re-render immediately fixes it".
Congrats!
anything you plan to work on post 2.0 release? I think defc doesn't implement react refresh yet?
I will write down a roadmap at some point. Not sure how feasible the fast refresh support is, the proof of concept branch did have some problems I was unsure about if they are fixable.
New hooks namespace API: https://reagent-project.github.io/docs/master/reagent.hooks.html I wonder how this will change clojurescript space, since it's making hooks more easy to reach. Up till now I didn't really see people use hooks in reagent code, wonder how this will affect it, especially for newcomers with react experience.
UIx has had the similar wrappers available - the cljs value helpers are copied from there
I think the mess that required :f> to use functional components has been a bigger issue
But I've used hooks in most Reagent projects in recent years, as they are very useful for many JS interop cases
> especially for newcomers with react experience. this is going to be a win win for people with js/react background
Yeah interop will be much easier, although up till now I usually was able to find a way to replace use-states etc. with ratom/functions/form-3 component
I will need to recalibrate my mental model 😅
Is there any benefit of using this:
(let [[count set-count] (hooks/use-state 0)] ...)
instead of this?
(defn counter []
(let [count (r/atom 0)]
(fn [] [:div {:on-click #(swap! count inc)} "Count: " @count])))
I'm wondering if hooks are better to be a default use or just a specific case
No benefit
Will reagent 2 still work with React 17 and React 18? From the changelog it sounds like it just won't be officially supported i.e. no tests
I'm quite sure it will work, just continue using reagent.dom/render. I haven't decided yet if I want to setup tests for React 18.
@juhoteperi Should I create an issue about it? Would an MRE be useful?
Some small example somewhere could be useful. It is very normal that the StrictMode will break your application with many Reagent patterns. No issue necessarily.
https://github.com/reagent-project/reagent/blob/master/doc/ReactFeatures.md#strictmode
Mm, right. Interesting that it applies only to React 19, apparently.
The async rendering does trigger more of these problems
It could be StrictMode does more tricks on concurrent mode (I.e., createRoot) than previously
So not necessarily difference with React 19 only
https://react.dev/blog/2022/03/29/react-v18#new-strict-mode-behaviors
I think it is very likely that change only affected concurrent mode on React 18
Ah, I see. I completely skipped React 18.
If you can find a small example, I might be able to say if there is something with Reagent component state that will cause the problem with StrictMode
Yeah, I'm working on making one.
There was a problem before the alpha3 that all ratoms broke with StrictMode: https://github.com/reagent-project/reagent/pull/640/files but I was able to test that it should work now
Alright, this is what I got.
@p-himik Will try later. On a few second glance, what might happen is that rendered-once is state is kept when StrictMode does render->unmount->render... and maybe that messes up state? Or maybe the rendered-once resets there, but then calc-metrics doesn't get called again.
Most libs, like re-frame, will work fine with Reagent 2.0, no need for changes.
Libs/tools that use Reagent to render components to dom, i.e., they call reagent.dom/render, will need an update to work with React 19 (they will work if you keep using React 18 because react-dom/render is still available.)
✅ https://github.com/metosin/reagent-dev-tools/issues/10 (version 1.1.0 supports Reagent 2/1.3 and React 18/19)
🟡 https://github.com/day8/re-frame-10x/issues/421 (works with React 19 with {:preloads [day8.re-frame-10x.preload.react-18]}, see readme)
https://github.com/flexsurfer/re-frisk/issues/87
I've enabled tests against React 18 in addition to 19: https://github.com/reagent-project/reagent/pull/646
Found the culprit - it's react/StrictMode which I use to wrap the whole app.
Without it, everything seems to work just as before.