Fork me on GitHub

ANNC: Here is a re-release of a hopefully instructive Reagent demo app,, a port of my JS Main enhancement is a minor tweak to avoid CORS issues that would prevent the thing even from running in a dev environment. Years ago I guess browsers locked down loading files from a directory; this avoids doing that. Next up is an attempted port to reagent 1.0.


That was easy ^^^^. +1 on the backward compatibility! Tough question: are there any killer features I am missing by sticking with “backwards”? Perusing the doc it seems 1.0 is about the segue to React hooks. I see also going that route is a bit slower. Did I just answer my own question? 🙂

Leonid Korogodski14:09:52

Hey, everyone. I'm new here.

👋 6
Leonid Korogodski15:09:01

Is this the right place to ask questions about specific problems we encounter when working with Reagent?


It sure is. Unless you're certain you're hitting a bug - then I'd just go straight to GitHub issues.

Leonid Korogodski15:09:35

No, I'm not certain. Still relatively new to Clojure.

Leonid Korogodski15:09:41

If you have a moment, take a look at the detailed description of the problem I have posted to Stack Overflow. I don't want to take the space here by copying and pasting the entire (lengthy) thing:


Oh, you're in for a treat. CLJS + Reagent + Material UI is a goldmine of similar issues. You write in the question: "Breaking in JS debugger, I see that inputRef.current is null" The reason is most likely due to the way Reagent passes the properties around. It does js->clj, more or less, and then clj->js. It creates copies of objects. But if something wants to pass the result of Reagent/createRef, which is just an object with a single key current, it won't work the right way because the original ref object will be lost. And the relevant React component expects that the object is preserved and is mutated by whatever sets the ref.


To overcome this, I manually convert text-input properties from JS to CLJS but in a shallow way (`js->clj` is deep).


And that works because Reagent doesn't try to convert JS props when it wants JS objects and CLJS props when it wants CLJS objects.

Leonid Korogodski15:09:57

Ah, interesting. Thanks! I'll try that.

Leonid Korogodski15:09:53

Not sure though how a different kind of conversion can help if the problem is that an object is lost.

Leonid Korogodski15:09:40

Unless the conversion is lossy at some point.


Consider this:

(-> #js {:ref #js {:current 1}} js->clj clj->js)
The resulting object will have the same information but it will be a different object in memory - any mutation to the original object will not be visible to the new one. Now consider this:
;; Assuming shallow-js->clj exists somewhere.
(-> #js {:ref #js {:current 1}} shallow-js->clj clj->js)
In this case, the inner object will be preserved - any mutation to the original object will be reflected in the new one.

Leonid Korogodski15:09:47

Aha, I see. Thanks again!

Leonid Korogodski15:09:11

Do you happen to have the code ready for shallow-js->clj , by any chance?



(defn shallow-js->clj-props [props]
  (into {}
        (map (fn [k]
               [(keyword k) (oget+ props k)]))
        (js-keys props)))
oget+ is from the cljs-oops library. Should be the same as goog.object/set, so you don't have to start using that library just because of this snippet.

🙌 3
Leonid Korogodski15:09:03

Nice library. I guess I'll use it, seeing as I don't currently use goog.object, either.


The thing is, goog.object is built-in because it comes with Google Closure library that CLJS uses.

Leonid Korogodski16:09:05

Ok, that didn't help, because the original js-params passed to render-input already have ref.current set to null.

Leonid Korogodski16:09:37

Do I need to copy it from InputProps.ref?


No, those are different refs. If you can create a repo with a minimal reproducible example, I could take a look and tell you what's wrong.