This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-10-03
Channels
- # babashka (5)
- # beginners (34)
- # biff (3)
- # calva (29)
- # cherry (11)
- # cider (7)
- # clojure (148)
- # clojure-brasil (1)
- # clojure-europe (16)
- # clojure-nl (1)
- # clojure-norway (6)
- # clojure-uk (6)
- # clojuredesign-podcast (8)
- # clojurescript (49)
- # cursive (1)
- # datalevin (7)
- # fulcro (1)
- # honeysql (1)
- # jobs (1)
- # matrix (7)
- # off-topic (13)
- # re-frame (12)
- # react (21)
- # reagent (42)
- # releases (6)
- # remote-jobs (2)
- # shadow-cljs (9)
- # solo-full-stack (5)
- # sql (7)
- # squint (9)
- # vim (2)
- # xtdb (11)
- # yamlscript (5)
hi, how much should I expect reagent to work with react 18.2 I am having the classical state is updated but component doesn't rerender problem and I have no idea why, from other examples online it looks like i am doing the same thing, but I've found 2 year old github issues unsolved with the same problem, so I am thinking, it's probably best to abandon ship?
I'm using react 18.2 with reagent and haven't encountered any issues, are you using any specific react features ?
hmm, I didn't think there will be an answer, but I am happy there is. give me a minute to bring alive one of my earliest minimal examples that I was struggling with
I haven't had issues with React 18. Example setup below (excerpts only, for brevity):
# Main CLJS app file
(ns client.app.main
(:require [reagent.core :as r]
[reagent.dom.client :as rdc]))
(defonce app-root
(rdc/create-root (.getElementById js/document "app")))
(def functional-compiler
(r/create-compiler {:functional-components true}))
(defn render []
(rdc/render app-root
<add your app here>
functional-compiler))
(defn ^:dev/after-load start []
(js/console.log "Start")
(render))
(defn ^:dev/export init []
(js/console.log "Initialize")
(start))
(defn ^:dev/before-load stop []
(js/console.log "Stop"))
I typically add the start
, init
, and stop
functions early in development to help me slot functionality in if need be at a later stage.
# package.json
{
"devDependencies": {
"shadow-cljs": "^2.25.2",
},
"dependencies": {
"react": "18.2.0",
"react-dom": "18.2.0"
}
}
sorry, this took longer than expected, actual work intervened, this example doesn't work for me at all, the console log is shown, so the render supposedly runs, but there is no visual update for the counter's value:
(ns app.browser
(:require
[reagent.core :as r]
[reagent.dom.client :as rdomc]
["react" :as react]))
(def !counter (r/atom 0))
(defonce react-root
(rdomc/create-root (js/document.getElementById "app")))
(defn comp1
[]
[:button {:class "button-class"
:on-click #(swap! !counter inc)}
"+"])
(defn app []
(js/console.log @!counter)
[:div.container
(str @!counter)
[comp1]])
(defn ^:dev/after-load start []
(rdomc/render react-root [:> react/StrictMode {} [:f> app]]))
(defn init []
(js/console.log "init")
(start))
(defn ^:dev/before-load stop []
(js/console.log "stop"))
This works for me:
(ns app.main
(:require [reagent.core :as r]
[reagent.dom.client :as rdc]))
(def !counter (r/atom 0))
(defonce app-root
(rdc/create-root (.getElementById js/document "app")))
(def functional-compiler
(r/create-compiler {:functional-components true}))
;; Components
(defn increment-counter []
[:button
{:on-click (fn [] (swap! !counter inc))}
"+"])
(defn app []
(js/console.log (str "Counter: " @!counter))
[:div
[:div
(str "Counter: " @!counter)]
[:div
[increment-counter]]])
(defn render []
(rdc/render app-root
[app]
functional-compiler))
;; ---
(defn ^:dev/after-load start []
(js/console.log "Start")
(render))
(defn ^:dev/export init []
(js/console.log "Initialize")
(start))
(defn ^:dev/before-load stop []
(js/console.log "Stop"))
I found the docs on the compiler (covers functional component implementation) quite helpful. https://github.com/reagent-project/reagent/blob/master/doc/ReagentCompiler.md#reagent-compiler
:f> was necessary originally because the actual problem came up when I was integrating cytoscape via an effect hook
But I can confirm that removing it makes the button work
the reagent component will be either a function component or a class component depending on the reagent compiler used
I will try this alternate solution to use functional components
well, the demo I constructed works without the :f> and my useeffect also works with the functional-compiler, but the state update -> component render still doesn't happen, even though I removed all :f>
is there some sure fire way to debug/troubleshoot this phenomenon?
looks to me that when I call my hook, everything else in the component is ignored afterwards
(def data (r/atom nil))
(defn setup-cyto [{:keys [cs config]}]
(cs config))
(defn use-cytoscape [element config els]
(react/useEffect
(fn []
(when (some? @element)
(let [js-els (clj->js els)
cy (setup-cyto {:cs cs
:config (config element js-els)})]
(-> cy
.nodes
(.on "click" #(reset! !koala (.id (.-target %)))))
(reset! data cy)
(.resize cy)
(.fit cy)
#(.destroy cy)))
js/undefined)))
just the hook for completeness
I use react hooks without issues, but have never used useEffect
(defn app [] [:f> use-cytospace]])
doesn't work ?
i'm just not sure you can use the ratom inside the useEffect function, and still have reactivity on the ratom change
but maybe just deref-ing the ratom in use-cytospace (outside useEffect) would work ? it's a bit of a hack 😕
what do you mean never used useEffect? how do you integrate third party tools then?
did you mean this line (.on "click" #(reset! !koala (.id (.-target %)))))
i'm not sure i follow, you were saying the component doesn't get re-rendered. What i'm saying is that I don't think use-cytoscape
will be re-rendered if element
changes here (unless you deref element
after useEffect (defn use-cytoscape [] (react/useEffect ...) @element [:<>])
that's it
will try in a moment, just work wouldn't be in the way
I am afraid no amount of derefing changes this. I think I am doing something wrong if it works for you, but I don't know what to look at. I have a bunch of console logs and only the ones that are before the use-cytoscape hook run more than once, all the rest runs at the first click but not again
i put derefs everywhere 😄
(def x (reagent/atom 0))
(defn a
[]
[:button
{:onClick #(swap! x inc)}
"click me"])
(defn b
[]
(react/useEffect
(fn [] (println "clicked !" @x) js/undefined))
@x
[:<>])
(defn app []
[:<>
[a]
[:f> b]])
the console.log appears for me too, but the value doesn't change
probably your code would though, as earlier the demo was working for me too without the :f>
the one being reset by the hook.
no, !koala 🙂
and I can check the element, but I would guess right now that it's not empty, the cytoscape graph being visible in it
ok so it doesn't really have anything to do with useEffect that line is a bit too specific to your lib so I can't help
thanks, you already helped immensely, at least i can be confident that this should work