A minimalistic ClojureScript interface to React.js

I'm not sure if this was already discussed in a github issue or in here: is there any interest in adding support for shortcut for divs as in sablono:

[:.ui.container>.message "hi"] vs [:div.ui.container>div.message "hi"]

haywood 2020-07-01T18:47:09.295400Z

👋:skin-tone-2: trying to debug this nagging cursor jumping issue when editing the middle of text in an input (cursor jumps to the end after change) I’m able to repro with this component

(defn input [{:keys [value on-change]}]
  (React/createElement "input" #js {:value value
                                    :onChange on-change}))

haywood 2020-07-01T18:47:17.295700Z

using the native [:input works though.

haywood 2020-07-01T18:49:02.296600Z

I’m using a native React component library, hence the createElement example

haywood 2020-07-01T19:02:15.297300Z

🙏:skin-tone-2: can’t believe I didn’t stumble upon that 🤦 thanks a lot this explains it.


Hi, I have a performance question concerning using React Motion with Reagent. I am wrapping the motion component in this way:

(defn motion
  "Creates a motion animation component from React Motion.

  The first parameter are animation attributes which a map having two maps stored as keys :style
  and :defaultStyle.
  - The :defaultStyle map describes the initial animation values when the component is mounted. When
    the component is later updated, :defaultStyle is ignored.
  - The :style map describes the current values which are targets of the animation.
  In both maps, the same keys have to be defined and these keys should be written in camelCase instead
  of kebab-case.
  - All values in :defaultStyle are numbers (nils not supported).
  - All values in :style are either numbers (which skips the animation and goes to the value directly),
    or are created by calling spring function defined below.

  The second parameter is an arbitrary Reagent component. It accepts a single argument which is the
  anim-props map containing the values of the current animation state.

  The third parameter is an input to the component which is stored unchanged as :data key into anim-props."
  [attr component data]
  [:> motion/Motion attr
   (fn [props]
     (when data
       (set! (.-data props) data))
     (r/create-element (r/reactify-component component) props))])
And using it like this:
(defn- zoom-buttons
  [{:keys [opacity]}]

       {:defaultStyle {:opacity 0}
        :style        {:opacity (anim/spring opacity)}}


Since we are animating many components at the same time (for a new graph layout), it would be helpful to make everything little bit faster.


For instance, I don't really need that React props are converted into Clojurescript map, I could just access data using js interop.


Or maybe I could make things faster by using some other tricks, not sure.

lilactown 2020-07-01T19:37:21.300800Z

you could probably move reactify-component outside of the render fn passed to the motion component

lilactown 2020-07-01T19:38:32.301100Z

in this case, I don't think props is being turned into a CLJS map

lilactown 2020-07-01T19:39:55.301400Z

have you profiled it to see why it might be slower than you want?


does destructuring works directly on JS objects?


moving reactify-component outside might help, I will test it out


what would you recommend for profiling?

lilactown 2020-07-01T19:47:17.302900Z

destructuring does not work on JS objects directly

lilactown 2020-07-01T19:47:32.303300Z

Chrome DevTools has an excellent profiler

lilactown 2020-07-01T19:50:40.304100Z

I would always suggest profiling your app to identify places to optimize. It might end up that this component isn't even the performance problem, but some parent component that's updating too frequently, taking too long, or something


I did a change recently with (set! ) which improved the performance quite a bit, so I think there is some bottleneck


before I was converting twice from JS->CLJS->JS


so there is likely more to be saved, the child component just have some styles updated via react


I will have to spend some more time getting used to the profiller, definitely worth investigating, probably I can save more on improving how links are drawn


this is how I can extract reactify-component out?

(let [react-component (r/reactify-component component)]
    (fn [attr _ data]
      [:> motion/Motion attr
       (fn [props]
         (when data
           (set! (.-data props) data))
         (r/create-element react-component props))]))


at the moment I can't decide whether it makes the code faster, or slower, or doesn't matter much at all (profilling makes it too noisy)

unbalanced 2020-07-01T23:13:10.309900Z

I find in practice there usually isn't a reason to have the value of the text area be controlled. An :on-focus or :on-blur typically does what is needed, or a submit button if it's within a form element. You can also do some fancier stuff with a type-3 component