continuous-integration/drone/push Build is passing
Details
|
||
---|---|---|
.. | ||
resources/public | ||
src/clojure_demo | ||
deps.edn | ||
dev.cljs.edn | ||
figwheel-main.edn | ||
package-lock.json | ||
package.json | ||
readme.org | ||
shadow-cljs.edn |
readme.org
Minimal clojurescript reagent reitit example
https://github.com/reagent-project/reagent
https://purelyfunctional.tv/guide/reagent/#what-is-reagent
https://github.com/metosin/reitit
https://www.metosin.fi/blog/reitit/
Figwheel Main
Figwheel is a tool that does hot reloading of your code, it greatly simplifys the tooling required to develop and deploy your applications.
Using this demo
Run at the shell with the below command, alternatively in your ide jack in using figwheel-main and the dev build when asked by your ide.
clj -m figwheel.main --build dev --repl
reload hooks
You can control how reloading works by using meta data in your project, usually adding it as a tag on your main namespace, and hooking your main function which calls reagent/render
see below for example hooks.
(ns ^:figwheel-hooks core.demo)
(defn ^:after-load render-site [])
Components
Reagent allow multiple ways to create components with increasing complexity. There is some good info in this article. https://purelyfunctional.tv/guide/reagent/
Form 1 components
Form one components are for simply rendering some html with values that are not going to change.
In the example below the function just returns some hiccup with the parameters inserted, you need to specify :key
when dynamically repeating the elements and these should be reproducible unique id's where possible not randomly generated or indexed numbers if the data is unordered.
(defn navbar-link [{:keys [href title text] :or {text nil title nil}}]
[:a.link.dim.white.dib.mr3 {:key href :href href :title title} text])
(defn product-card
[{:keys [title amount description link]}]
[:article.br2.ba.dark-gray.b--black-10.ma2.w-100.w-50-m.w-25-l.mw5
[:img.db.w-100.br2.br--top {:src link}]
[:div.pa2.ph3-ns.pb3-ns
[:div.dt.w-100.mt1
[:div.dtc [:h1.f5.f4-ns.mv0 title]]
[:div.dtc.tr [:h2.f5.mv0 amount]]]
[:p.f6.lh-copy.measure.mt2.mid-gray description]]])
(product-card
{:title "Cat 01"
:amount "£54.59"
:description "Cat description here"
:link "http://placekitten.com/g/600/300"})
Form 2 components
In form two we can track local state inside a component a click counter being a basic example.
Form 3 components
This form of component give's you full access to the react life cycle methods, so render did-mount did-unmount etc
usually this form of component is only needed when rendering graphics or things like graphs, it's also useful for capturing errors and handling them as in the example below, which renders your components but if component-did-catch
is trigger the error is caught and displayed instead.
(defn err-boundary
[& children]
(let [err-state (reagent/atom nil)]
(reagent/create-class
{:display-name "ErrBoundary"
:component-did-catch (fn [err info]
(reset! err-state [err info]))
:reagent-render (fn [& children]
(if (nil? @err-state)
(into [:<>] children)
(let [[_ info] @err-state]
[:pre [:code (pr-str info)]])))})))
Routing
Routing with reitit is all about data, you store your routes as nested vectors of hash maps. the hash map should take a name and view param at least but you can add in params and validate the data.
Reitit works as a backend and frontend routing library so you can share routes between the two.
These are a few simple routes, the last takes parameters and does validation checking against the values.
(def routes
[["/"
{:name ::frontpage
:view home-page-function}]
["/about"
{:name ::about
:view about-page-function}]
["/item/:id"
{:name ::item
:view item-page-function
:parameters {:path {:id int?}
:query {(ds/opt :foo) keyword?}}}]])
You need to connect your routes data structure to ref/start!
this function take's your own function where you can handle what should happen on route change, in this example an atom is updated causing react to render the new page.
(rfe/start!
(rf/router routes {:data {:coercion rss/coercion}})
(fn [m] (swap! site-state assoc :current-route m))
;; set to false to enable HistoryAPI
{:use-fragment true})
To create a link to a route, you can use the rfe/href
function which takes a lookup key which you specified in your routes, in this instance the key is name spaced to the current namespace.
[:a {:href (rfe/href ::frontpage)} "example link"]