This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-01-24
Channels
- # announcements (3)
- # aws (5)
- # babashka (10)
- # beginners (61)
- # calva (22)
- # clara (9)
- # clj-kondo (8)
- # cljdoc (8)
- # cljsrn (15)
- # clojure (44)
- # clojure-australia (2)
- # clojure-europe (31)
- # clojure-hungary (20)
- # clojure-nl (5)
- # clojure-uk (3)
- # core-logic (2)
- # cursive (2)
- # data-science (2)
- # datalevin (4)
- # datascript (6)
- # datomic (17)
- # defnpodcast (1)
- # figwheel-main (1)
- # fulcro (18)
- # graalvm (2)
- # introduce-yourself (2)
- # jobs (1)
- # jobs-discuss (59)
- # lsp (44)
- # music (1)
- # nrepl (2)
- # off-topic (26)
- # pedestal (2)
- # re-frame (12)
- # reagent (27)
- # releases (1)
- # remote-jobs (4)
- # rewrite-clj (2)
- # sci (12)
- # shadow-cljs (12)
- # sql (10)
- # uncomplicate (6)
- # vim (12)
- # xtdb (2)
I’m trying to embed cljs react components in an existing javascript codebase. I’m using shadow-cljs to compile my cljs to js and using reagent with /reactify-component
to produce components. My JSX is being picked up, but my button :on-click
is not being called in the js ecosystem
Any insight on how to embed reagent in a native react js ecosystem would be greatly appreciated
Hard to say without seeing the actual code. But just in case - do you compile both JS and CLJS using shadow-cljs? If not, how do you make sure that you have only a single copy of React in your app? Because by default, if you just build CLJS then the resulting JS bundle will have a copy of React on its own.
That’s likely my problem. I have an existing next js app with its own internal webpack setup. We’re seeing if an incremental migration to cljs is possible by exporting js
files from our shadow-cljs setup
Trying simple hello world examples, but my button event handlers aren’t working in the javascript environment
Are you using :target :browser
or other Shadow-CLJS target? Check if the output file contains copy of React.
You should be able to configure Shadow-CLJS output to use React from the webpack bundle with js-provider option: https://shadow-cljs.github.io/docs/UsersGuide.html#js-provider
Or if you are already using :target :npm-module the :js-provider :require should be the default already and React shouldn't be included in the output. Haven't tried this setup.
Or if your shadow-cljs output isn't processed by webpack, you could use :resolve
to tell shadow-cljs to get React object from a global variable: https://shadow-cljs.github.io/docs/UsersGuide.html#js-resolve (then you also need to ensure webpack will publish React in the global var)
And problems with event handlers does sound like something that can be caused by having multiple React versions loaded in the page, due to how React implements event handling.
@U061V0GG2 I’m using :npm-module
target
I’ll check if I have a react copy. All I see is a shimmed one: require("./shadow.js.shim.module$react.js");
@U05224H0W I’m running shadow-cljs watch app
with the following config:
{:source-paths
["src"]
:dependencies
[[reagent "1.1.0"]]
:builds
{:app {:target :npm-module
:output-dir "../frontend/cljs"
:asset-path "/js"
:devtools {:after-load app/main}
:modules {:main {:init-fn app/main}}}}}
My cljs source looks like so:
(ns app
(:require [react :as react]
[reagent.core :as r]
[reagent.dom :as rd]))
(defn app [props]
(let [[incs set-incs] (react/useState 0)
[decs set-decs] (react/useState 0)
total (+ incs decs)]
(react/useEffect #(print (str "total " total)) #js[array incs decs])
[:div
[:p "props: " (prn-str props)]
[:p "total: " total]
[:p "increments: " incs]
[:p "decrements: " decs]
[:button {:on-click #(set-incs inc)} "Increment"]
[:button {:on-click #(set-decs dec)} "Dec"]]))
(defn func-comp [props] [:f> app props])
(def react-comp (r/reactify-component func-comp))
Then in javascript react files, I import the reactified component like so: import { react_comp as ReactComponent } from 'cljs/app'
It renders the JSX correctly and logs the use effect print statement, but the button event handlers are not firing
Using the app func directly in my JSX seems to behave the same way
{:on-click #(set-incs inc)}
react/useState
is an actual set
not a swap!
. so you setting it to the inc
function unless I'm missing something?
I would assume that the on-click actually fires but then fails one re-render since (+ incs decs)
will fail when incs
is the inc
function?
If setState
update if is given a function, React will call that with the current value etc. so it works as both reset! and swap!
Event handlers were working fine the whole time… I was preventing click events with css essentially :face_palm: