ajmorgan
12/15/2015 - 11:30 PM

d3-reagent-component.cljs

(ns foo.component.test-component
  (:require [reagent.core :as r]))


(defn- draw-d3
  [data]
  (let [update (-> js/d3 (.select ".foo-component") (.selectAll "div.h-bar") (.data (clj->js @data)))
        enter (-> update .enter)
        exit (-> update .exit)]
    (-> enter
        (.append "div")
        (.attr "class" "h-bar")
        (.append "span"))
    (-> update
        (.style "width", (fn [d] (str (* d 3) "px")))
        (.style "background-color", "lightgrey")
        (.select "span" )
        (.text (fn [d] d)))
    (-> exit
        .remove)))

(defn foo-component [args]
  (let [dom-node (r/atom nil)]
    (r/create-class
     {:component-did-update
      (fn [this old-argv]
        (let [[_ args] (r/argv this)]
          ;; This is where we perform our d3.
          (draw-d3 args)))

      :component-did-mount
      (fn [this]
        (let [node (r/dom-node this)]
          ;; This will trigger a re-render of the component.
          (reset! dom-node node)))

      :reagent-render
      (fn [args ...]
        ;; Necessary for Reagent to see that we depend on the dom-node and 
        ;; args r/atoms.  Note: we don't render D3 at this point.  We have 
        ;; to wait for the update.
        @dom-node
        @args
        [:div
         [:div.foo-component]])})))

(def state
  (r/atom [10 15 40 60 80 65 55 30 20 10 8]))

(defn component []
  (let [necessary-state state]
    [foo-component necessary-state]))