This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-03-06
Channels
- # adventofcode (2)
- # announcements (5)
- # architecture (4)
- # babashka (35)
- # beginners (28)
- # calva (4)
- # cider (9)
- # clerk (30)
- # clj-kondo (11)
- # clojure (58)
- # clojure-conj (3)
- # clojure-europe (71)
- # clojure-gamedev (2)
- # clojure-nl (3)
- # clojure-uk (2)
- # clojurescript (49)
- # conjure (2)
- # cursive (2)
- # emacs (4)
- # fulcro (1)
- # honeysql (2)
- # hyperfiddle (10)
- # jobs (2)
- # jobs-discuss (18)
- # leiningen (9)
- # membrane (14)
- # missionary (1)
- # off-topic (27)
- # pedestal (1)
- # polylith (5)
- # reagent (12)
- # releases (2)
- # remote-jobs (3)
- # shadow-cljs (83)
- # sql (5)
- # squint (14)
- # tools-build (13)
Hello 🙂
In new versions of reagent, I get a warning that reagent.dom/dom-node
is deprecated, however the documentation does not say what to replace it with.
My use-case:
I have a very simple component that’s a code block <code></code>
.
On mount of this component, I want to call highlight JS’ highlightElement
.
I have code which looks like this:
(defn highlight-element
[el]
(.highlightElement hljs (reagent.dom/dom-node el)))
(defn code-block
([s lang]
(reagent/create-class
{:reagent-render (fn [s] [:code (when lang {:class lang}) s])
:component-did-mount highlight-element
:component-did-update highlight-element})))
Can someone please help me figure this out?Note also that :component-did-mount
receives not el
but this
- an instance of the component itself and not its corresponding DOM node (which might not even exist).
oh boy
Thanks for the info and quick reply! On to learning about React refs then.
In this case, it'll be something as simple as:
;; The exact `:require` vector might be different, depends on your build tool.
;; I'm using only shadow-cljs - this works there just fine.
(require '["react" :as react]
'[reagent.core :as r])
(defn highlight-element
[el]
(.highlightElement hljs el))
(defn code-block
;; Note that I moved `lang` to the render fn since otherwise changing the arg would not cause a re-render.
[_ _]
(let [ref (react/createRef)]
(r/create-class
{:reagent-render (fn [s lang]
[:code {:ref ref
;; No need for `when` here, even if `lang` is `nil`.
:class lang}
s])
:component-did-mount (fn [_this]
(highlight-element (.-current ref)))
:component-did-update (fn [_this _old-argv _old-state _snapshot]
(highlight-element (.-current ref)))})))
Is there a reason why I should not do this?
(defn highlight-element
[el]
(.highlightElement hljs el))
(defn code-block
([s]
(code-block s nil))
([s lang]
[:code
{:ref (fn [el] (when el (highlight-element el)))
:class lang}
s]))
Ah, I guess the ref callback is called twice, so sometimes el
can be nil
, which causes the call to highlight JS to fail.
As far as I understand, I do not need the :component-*
callbacks anymore.
Looks like it’s working like a charm on my end. 🙂 I only removed code 🥳
Ref fn is called when the component is mounted or unmounted, which might not happen always when s
changes. So it is possible the highlights aren't always updated when the code changes.
One option would be to use useEffect
hook to trigger the call when ref or code changes:
(let [ref (react/useRef)]
(react/useEffect
(fn []
(when (.-current ref)
(.highlightElement (.-current ref)))
js/undefined)
#js [(.-current ref) s])
[:code ...])
Something like this.Or useEffect
without the dependencies would run after every render similar to componentDidMount
+ componentDidUpdate