Skip to content

Instantly share code, notes, and snippets.

@rgm

rgm/core.cljs Secret

Last active November 26, 2017 01:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rgm/0e75c4bf069a9136e98179d9596c4bae to your computer and use it in GitHub Desktop.
Save rgm/0e75c4bf069a9136e98179d9596c4bae to your computer and use it in GitHub Desktop.
re-frame + d3 together, trying to mesh d3's enter|update|exit with react lifecycle methods and re-frame subs.
(ns reagent-d3-test.core
(:require [reagent.core :as reagent]
[re-frame.core :as re-frame]
[cljsjs.d3]))
;;; --------------------
;;; db
(def default-db
{:data '()})
;;; --------------------
;;; events
(re-frame/reg-event-db
::initialize-db
(fn [_ _]
default-db))
(re-frame/reg-event-db
::add-one
(fn [db _]
(update db :data conj {:date (str (js/Date.))})))
(re-frame/reg-event-db
::remove-one
(fn [db _]
(update db :data #(drop 1 %))))
;;; subs
(re-frame/reg-sub
::data
(fn [db]
(:data db)))
;;; --------------------
;;; views
;;; D3
(defn d3-enter [dom-target data]
(-> (js/d3.select dom-target)
(.selectAll "li")
(.data (clj->js data))
(.enter)
(.append "li")))
(defn d3-update [dom-target data]
(-> (js/d3.select dom-target)
(.selectAll "li")
(.data (clj->js data))
(.text #(.-date %))))
(defn d3-exit [dom-target data]
(-> (js/d3.select dom-target)
(.selectAll "li")
(.data (clj->js data))
(.exit)
(.remove)))
(defn inner-did-update [dom-target data]
(println "inner-did-update")
(d3-enter dom-target data)
(d3-update dom-target data)
(d3-exit dom-target data))
(defn inner-did-mount [dom-target data]
(println "inner-did-mount")
;; already created <ul> in hiccup and saved off a ref,
;; no need to create the container here
(inner-did-update dom-target data))
;;; reagent/reframe entry points
;;; per https://gadfly361.github.io/gadfly-blog/posts-output/2016-10-22-d3-in-reagent/
(defn inner-d3
"renders items into a <ul> to test D3 lifecycle"
[{:keys [data]}]
(let [dom-target (reagent/atom nil)]
(reagent/create-class
{:display-name
"d3-inner"
:component-did-mount
(fn [comp]
(let [{:keys [data]} (reagent/props comp)]
(inner-did-mount @dom-target data)))
:component-did-update
(fn [comp]
(let [{:keys [data]} (reagent/props comp)]
(inner-did-update @dom-target data)))
:reagent-render
(fn [{:keys [data]}]
(js/console.log "inner-d3 sees" (count data) "items")
[:div "d3 view:"
[:ul {:ref #(reset! dom-target %)}]])})))
(defn outer-re-frame
"hold re-frameyness out here so we can use devcards with inner-d3"
[]
(let [data (re-frame/subscribe [::data])]
(js/console.log "outer-re-frame sees" (count @data) "items")
(fn []
[:div
[inner-d3 {:data @data}]
[:hr]
[:button {:on-click #(re-frame/dispatch [::add-one])} "add one"]
[:button {:on-click #(re-frame/dispatch [::remove-one])} "remove one"]
[:div "sub returning: "
[:p [:code (str @data)]]]])))
;;; --------------------
;;; core
(defn dev-setup []
(enable-console-print!)
(println "dev mode"))
(defn mount-root []
(re-frame/clear-subscription-cache!)
(reagent/render [outer-re-frame]
(.getElementById js/document "app")))
(defn ^:export init []
(re-frame/dispatch-sync [::initialize-db])
(dev-setup)
(mount-root))
(defproject reagent-d3-test "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.8.0"]
[org.clojure/clojurescript "1.9.908"]
[reagent "0.7.0"]
[re-frame "0.10.2"]
[cljsjs/d3 "4.12.0-0"]]
:plugins [[lein-cljsbuild "1.1.5"]]
:min-lein-version "2.5.3"
:source-paths ["src/clj"]
:clean-targets ^{:protect false} ["resources/public/js/compiled" "target"]
:figwheel {:css-dirs ["resources/public/css"]
:server-port 3450}
:profiles
{:dev
{:dependencies [[binaryage/devtools "0.9.4"]]
:plugins [[lein-figwheel "0.5.13"]]}}
:cljsbuild
{:builds
[{:id "dev"
:source-paths ["src/cljs"]
:figwheel {:on-jsload "reagent-d3-test.core/mount-root"}
:compiler {:main reagent-d3-test.core
:output-to "resources/public/js/compiled/app.js"
:output-dir "resources/public/js/compiled/out"
:asset-path "js/compiled/out"
:source-map-timestamp true
:preloads [devtools.preload]
:external-config {:devtools/config {:features-to-install :all}}
}}
{:id "min"
:source-paths ["src/cljs"]
:compiler {:main reagent-d3-test.core
:output-to "resources/public/js/compiled/app.js"
:optimizations :advanced
:closure-defines {goog.DEBUG false}
:pretty-print false}}
]}
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment