Hello everyone!

I implemented a slider component in Reagent + D3 using reagent/create-class:

 (ns slider
  (:require [reagent.core :as reagent]
                [reagent.impl.util :as util]))

(defn slider  [{:keys [name width height value on-change]}]
  (let [w (or width 150)
        h (or height 20)]

    (reagent/create-class {
      :component-did-mount
        (fn [this]
          (let [pos->value   #(-> js/d3 (.mouse (.getDOMNode this)) first (/ w) 
(min 1) (max 0))
                on-drag      #(on-change (pos->value))
                drag         (-> js/d3 .-behavior .drag
                                 (.on "drag" on-drag))]
            (-> js/d3
                (.select (.getDOMNode this))
                (.call drag))))

      :render (fn [this]
        (let [value (-> this util/get-props :value)]
          [:svg {:width w :height h}
            [:g {:className "slider"}
              [:rect {:className "slider__rect"  :x 1 :y 1 :width (- w 3) 
:height (- h 3) }]
              [:rect {:className "slider__fill__rect"
                      :x 2 :y 2
                      :width (- (* w value) 4) :height (- h 4) }]
              [:text {:className "slider__text" :x (/ w 2) :y (/ h 2)} 
name]]]))})))


Here the properties of the component are specified in the outer "slider" 
function. The values of these function params, however, are not getting updated 
when accessed from the inner render function on subsequent calls, of course. So 
the value of the parameter "value" always stays the same as when the component 
was first created, even if the actual property has changed. This is ugly and 
was a source of confusion for me.

I could resort to calling reagent.impl.util/get-props to get the most current 
property values in "render", and it works. However, get-props seems to be an 
internal function, so it is probably not intended to be called directly.

When using the alternative way of constructing components with "with-meta", the 
properties are passed as parameters directly to the render function. Hence, 
render always sees the most current values:

(def slider
  (with-meta
    (fn [{:keys [name width height value on-change]}] ...)

    {:component-did-mount
      (fn [this] ...)}))

This way there is at least less confusion, because there are no variables with 
obsolete property values here. But component-did-mount does not get the 
properties directly and has to use get-props again.

Personally, I would prefer using create-class for components with extra 
life-cycle functions, but this confusion with the variables getting obsolete 
makes it much less attractive than it could be. 


Am I missing something obvious?  What is the proper way of defining component 
properties which allows all the life-cycle functions to see them? 



Thanks in advance!
Ilya

-- 
Note that posts from new members are moderated - please be patient with your 
first post.
--- 
You received this message because you are subscribed to the Google Groups 
"ClojureScript" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/clojurescript.

Reply via email to