how to rerender reagent ui with react 18 and shadow-cljs reload?
Asked Answered
K

2

6

how to rerender the whole reagent tree when we save file and shadow-cljs reloads?

  • react 18 has new createRoot api
  • and even before - if nothing changed calling render has no effect
Kana answered 26/5, 2022 at 9:22 Comment(0)
C
18

With react v18, you need to create the root node only once. After this, you can call the .render() function from it to (re-)render your application.

Also, you need to configure a function / behavior to tell shadow-cljs what it should do on during reload.

Here is a full example, taken from here https://github.com/schnaq/cljs-reagent-template

(ns playground
  (:require ["react-dom/client" :refer [createRoot]]
            [goog.dom :as gdom]
            [reagent.core :as r]))

(defn- main []
  [:main.container.mx-auto
   [:h1 "Welcome to your app"]])

;; -----------------------------------------------------------------------------

(defonce root (createRoot (gdom/getElement "app")))

(defn init
  []
  (.render root (r/as-element [main])))

(defn ^:dev/after-load re-render
  []
  ;; The `:dev/after-load` metadata causes this function to be called
  ;; after shadow-cljs hot-reloads code.
  ;; This function is called implicitly by its annotation.
  (init))

shadow-cljs is configured to call the init-function from playground/init.

;; shadow-cljs.edn
{...
 :builds {:frontend {:modules {:main {:init-fn playground/init}}}}}
Condolent answered 2/6, 2022 at 14:11 Comment(3)
Hi, I am curious if you could explain why you chose in the github repo to downgrade to React 17?Lithoid
Because of re-frame-10x. This is a powerful tool, but hooks into the Dom with the old method, which is no longer supported in react 18. I described it in this issue. We don't want to miss 10x during development, which keeps us on react 17. But we are considering upgrading it ourselves, because the shadow-cljs console is spammed with deprecation warnings, which makes development very messy...Condolent
Oh, but I did not add re-frame and 10x to this repo 😅 so I could stick to react v18 in this project. I built this as an extract of our main project, which was not yet open sourced to the date of this answer.Condolent
K
-2

https://github.com/move-me-to-ipfs-shipyard/Fennec/blob/bbfb566211041dd57b419ffd95f642026bb989a8/src/Fennec/ui.cljs#L263

(:require 
  ["react-dom/client" :as Pacha.dom.client]
  [reagent.core :as Kuzco.core])

; seed.cljs
(defonce root {:dom-rootA (atom (Pacha.dom.client/createRoot
                                 (.getElementById js/document "ui")))})

; ui.cljs
(:require [Fennec.seed :refer [root]])

(defn reload
  []
  (when-let [dom-root @(:dom-rootA root)]
    (.unmount dom-root)
    (let [new-dom-root (Pacha.dom.client/createRoot
                        (.getElementById js/document "ui"))]
      (reset! (:Pacha-dom-rootA root) new-dom-root)
      (.render @(:Pacha-dom-rootA root)
               (Kuzco.core/as-element [rc-current-page])))))
Kana answered 26/5, 2022 at 9:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.