Contents

ClojureScript and Dynamic!? Re-charts

Contents

I simply forgot how easy it was to use ClojureScript for charting.

Someone got in touch with me recently to give them an example on how things are again, so here it is.

The data set is an atom, so that eventually the reagent/react reactive rendering framework can be used as its best.

(defonce data (r/atom [  {:name "Page A" :uv 4000 :pv 2400}
                         {:name "Page B" :uv 3000 :pv 1398}
                         {:name "Page C" :uv 2000 :pv 9800}
                         {:name "Page D" :uv 2780 :pv 3908}
                         {:name "Page E" :uv 1890 :pv 4800}
                         {:name "Page F" :uv 2390 :pv 3800}
                         {:name "Page G" :uv 3490 :pv 4300}]))

The chart is a two lines chart, one for the uv series, and one for the pv series.

(defn chart []
[:> LineChart {:width 500 :height 300 :data @data}
 [:> XAxis {:dataKey "name"}]
 [:> YAxis]
 [:> CartesianGrid {:stroke "#eee" :strokeDasharray "5 5"}]
 [:> Line {:type "monotone" :dataKey "uv" :stroke "#8884d8" }]
 [:> Line {:type "monotone" :dataKey "pv" :stroke "#82ca9d" }]])

The chart component is then mounted using react-dom, with rd/render.

(rd/render
    [chart]
    (.getElementById js/document "app"))

The data refresh logic for this example looks way more complicated than it really is.


(defn update-data []
  (js/setInterval
    (fn []
      (swap!
        data
        (fn [current-data]
          (mapv (fn [d] (assoc d :uv (+ (:uv d) (- (rand-int 1000) 100))
                                 :pv (+ (:pv d) (- (rand-int 1000) 100))))
                current-data))))
    2000))

This is simply a javascript timer, updated the values of each serie one by one. A more realist scenario would be to have a websocket pushing the new data to the atom.

And the chart is rendered.