Fork me on GitHub
#shadow-cljs
<
2023-03-07
>
jeaye00:03:55

I'm making a JS lib from a CLJS lib, using :target :esm. This CLJS lib is using React/Reagent and the JS lib is meant to be used within a React app. But the JS lib is consumed via CDN, rather than using webpack or similar, since multiple apps all use it and I need them on the same version. Will the duplicate React code lead to issues here? And is there a way around this with shadow-cljs?

hifumi12300:03:29

My big concern here is whether reagent components can be consumed from “vanilla React” given that reagent structures props and rendering in a very different way to most other React components. (i.e. while we can re-use react components in reagent, we cannot necessarily re-use reagent components in react)

jeaye00:03:26

My understanding is that Reagent components can be turned into React components.

hifumi12301:03:09

Yup — that same link was posted in the thread I referenced, but apparently it’s only for use within a reagent app

hifumi12301:03:48

The good news is that you will have some luck with Helix, whose components are always plain old React components. This makes them very natural to embed into vanilla JS and even in react components that let you pass in a component (e.g. material ui's list component, which accepts a list item prop if you want to bring your own list item component)

hifumi12301:03:17

in that case i think your distribution issues can be solved by deciding a minimum react version (e.g. 16) and building against it — I don’t think react has to be bundled in this case, but users of your library will have to be aware of compatible react versions

jeaye01:03:52

Hm, my CLJS lib is already built with React. Extracting from a CLJS app, to make the functionality available to other JS apps.

jeaye01:03:22

Seems like I'd need to rewrite the views I want to share in Helix. Maybe all of them, if Helix can't coexist with Reagent.

hifumi12301:03:47

Helix can coexist with reagent just fine. The caveat is that reagent views are functions returning hiccup, which need to be interpreted into a react component. This is done with r/as-element

hifumi12301:03:49

I want to say the bigger concern here is being able to refactor Hiccup in a way that plays nicely with Helix, assuming you’d want to refactor reagent code into helix code. I believe Helix lets you define your own defnc macro so that you can use Hiccup, but it’s an “opt in” feature and it needs some work to set up

jeaye01:03:07

Thanks for the info. This was quite the surprise. That reagent fn's docs could really be more clear that it's not creating react components that can be used in a react app.

thheller06:03:06

how does the other react app provide react to js libs?

thheller06:03:16

two react version is very likely to cause problems

thheller06:03:11

and if the other app provides an import map, it could provide the react version it uses that way? https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap

thheller06:03:51

or :js-options {:keep-as-import #{"react" "react-dom"}} to only keep those two as regular import but have the rest bundled also works

thheller06:03:41

it really all depends on how the react app you are trying to integrate with is built

thheller06:03:23

it could also be providing a global React variable, where you'd do this https://shadow-cljs.github.io/docs/UsersGuide.html#js-resolve

thheller06:03:25

FWIW you can use reagent components from react directly just fine. just needs to be the reactify-component thing, not the plain fn

thheller06:03:19

but even the plain fns will work if you wrap them as (defn my-component [props] (r/as-element [the-actual-thing ...]))

thheller06:03:56

there is no need for helix, but that is an option too of course

Victor Pigmeo14:03:34

Hey everyone, newbie question, I'm starting my first project with cljs , I use npx create-cljs-project command to create my project, I want to use react also so I did a yarn add react, but I didn't find on the docs any example of a initial file setup to run my project with a simple "Hello World" div. When I try to yarn shadow-cljs watch app (I setup the app :build on shadow-cljs.edn) and I access on my browser the :port I setup on the shadow-cljs.edn I got an error: ERROR: java.lang.ArithmeticException: long overflow could anyone please point me some example or some guide on how to setup correctly react on my project? A example project would be nice so I can see how things are made on a real project. Thx in advance. 🙂

thheller14:03:14

what does your config look like? not sure which :port you are referring to?

thheller14:03:33

the first hello world sort of depends on which react wrapper you want to use

thheller14:03:46

might be quicker to start with a re-frame template?

thheller14:03:19

create-cljs-project is the bare minium, without any assumption that you are even going to build a web frontend

Victor Pigmeo15:03:49

Thx, I was refering to the nrepl port, but I saw that maybe I need to setup the dev-http instead. I'll take a look on that project after lunch thanks3

thheller15:03:39

:dev-http is the http server yes. nrepl is what your editor would use to connect.

Victor Pigmeo16:03:45

With that project and https://maksimrv.medium.com/setup-shadow-cljs-react-project-36a14e9f07d5 now everything works properly 🙂 I can run, the auto-refresh worked well and also react is working. Thanks again, awesome project

thheller16:03:46

please don't do this 😛

(defn main []
  (let [app-node (.getElementById js/document "app")]
    (rdom/render [app] app-node)))
(main)

thheller16:03:20

instead do

(defn main []
  (let [app-node (.getElementById js/document "app")]
    (rdom/render [app] app-node)))

(defn ^:dev/after-load reload! []
  (main))

thheller16:03:22

and in your build config instead of {:entries [core]} {:init-fn core/main}

Victor Pigmeo16:03:22

hmm makes sense to use lifecycle, I'll read ASAP, thank you