3

We are using chart.js with clojurescript and Reagent. Now I know that Chart.js has a chart.update() method to update the chart with new data. So the question is, how can I setup my component so that it renders the chart on :reagent-render but probably get :component-will-update to call the chart.update() method ?

Basically, is there a way to get a handle on the chart that is created from :reagent-render function in :component-will-update function ?

Amit Shah
  • 107
  • 6

1 Answers1

1

The usual pattern you follow in this case is to wrap the stateful/mutable object in a React component and use React's lifecycle methods.

The approach is described in detail in re-frame's Using-Stateful-JS-Component but this is how I tend to do it with D3:

(defn graph-render [graph-attrs graph-data]
  ;; return hiccup for the graph here
  (let [width (:width graph-attrs)
        height (:height graph-attrs)]
    [:svg {:width width :height height}
     [:g.graph]]))

(defn graph-component [graph-attrs graph-data]
  (r/create-class
   {:display-name "graph"
    :reagent-render graph-render
    :component-did-update (fn [this]
                            (let [[_ graph-attrs graph-data] (r/argv this)]
                              (update! graph-attrs graph-data)))
    :component-did-mount (fn [this]
                           (let [[_ graph-attrs graph-data] (r/argv this)]
                             (init! graph-attrs graph-data)))}))

(defn container []
  [:div {:id "graph-container"}
   [graph-component
    @graph-attrs-ratom
    @graph-data-ratom]])

It is important to keep the outer/inner combination because React won't populate its props correctly otherwise.

Another thing to be carefully of is the return of the reagent/argv vector, which, as you can see, contains the props after the first item. I have seen (reagent/props comp) in the wiki page above but I have never tried it myself.

Andrea Richiardi
  • 703
  • 6
  • 21