Let's say you want to split out a library of UI components into a separate bundle, so that it can be shared across multiple applications that depend on the library.
(ns app.ui.lib
(:require [uix.core :refer [defui $]]))
(defui modal [{:keys [on-close children]}]
...)
Similarly to React, with UIx you can use uix.core/lazy
that will take care of loading the UIx component from a separate module. Then in UI code you can use React's Suspense
to load the component lazily and display a fallback UI while it's loading. The example below demonstrates how to create and load a lazy component using the loader API from shadow-cljs.
(ns app.core
(:require [uix.core :refer [defui $]]
[shadow.lazy]))
;; create shadow's loadable object that references `app.ui.lib/modal` component
(def loadable-modal (shadow.lazy/loadable app.ui.lib/modal))
;; create React's lazy component that loads the modal using shadow's API
(def modal (uix.core/lazy #(shadow.lazy/load loadable-modal)))
(defui app []
(let [[show-modal? set-show-modal!] (uix.core/use-state false)]
($ :div
($ :button {:on-click #(set-show-modal! true)})
;; wrap the "lazy" `modal` with React's `Suspense` component and provide a fallback UI
($ uix.core/suspense {:fallback ($ :div "Loading...")}
(when show-modal?
;; when rendered, React will load the module while displaying the fallback
;; and then render the component referenced from the module
($ modal {:on-close #(set-show-modal! false)}))))))
For the above to compile correctly you'd have to update build config in shadow-cljs.edn
:
{:module-loader true
:modules {:main {:entries [app.core}}
:ui-lib {:entries [app.ui.lib}
:depends-on #{:main}}}
If you are not familiar with ClojureScript's :modules
configuration, make sure to read documentation about this compiler option.
Also check out React's documentation page on Code-splitting and React.lazy for more examples.
If you are using shadow-cljs and doing traditional hot-reloading aka re-render from the root, then the above setup is not going to work. However it can be easily fixed. The only change required is to provide shadow's loadable
as the second argument to uix.core/lazy
.
(def modal (uix.core/lazy #(shadow.lazy/load loadable-modal)
loadable-modal))
Can you improve this documentation? These fine people already did:
roman01la, Roman Liutikov & Shaun MahoodEdit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close