Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Radium doesn't work with Reagent (Clojurescript)?

I was trying to get working FormidableLabs/radium · GitHub with reagent-project/reagent · GitHub, but I've come to a dead end.

I was able to get it working partially by "hacking" reagent function create-class like this (It's almost the same as original, I just added js/Radium wrapper).

(ns myproject.components.radium
  (:require [reagent.core :as r]
            [reagent.impl.component :as c]
            [reagent.impl.util :as util]
            [reagent.interop :refer-macros [.' .!]]))

(defn create-class
  [body]
  (assert (map? body))
  (let [
        spec (c/cljsify body)
        res (js/Radium (.' js/React createClass spec))
        ;res (.' js/React createClass spec)
        f (fn [& args]
            (r/as-element (apply vector res args)))]
    (util/cache-react-class f res)
    (util/cache-react-class res res)
    f))

Then I made function for component like this

(defn radium []
  (create-class
    {:reagent-render
     (fn []
       [:button {:style
                 [{:backgroundColor             "red"
                   :width                       500
                   :height                      100
                   "@media (min-width: 200px)" {:backgroundColor "blue"}
                   ":hover"                     {:backgroundColor "green"}}
                  {:height 200}]}
        "Heres something"])}))

And I use it somewhere in some other reagent render function like: [radium/radium]

  • So, merging vector of styles together works well (That's Radium feature).
  • Media query works also, but only on first render, it doesn't react dynamically when I change screen size.
  • :hover :focus :active doesn't work at all

I was digging in Radium code to found out what's wrong. Good sign was that Radium properly assigns onMouseEnter onMouseLeave props to the component and sets :hover state of component to true.

This gets properly fired: https://github.com/FormidableLabs/radium/blob/master/modules/resolve-styles.js#L412

The problem is that render function, which is supposed re-render component based on new state (changed by Radium) is not fired at all. This render function: https://github.com/FormidableLabs/radium/blob/master/modules/enhancer.js#L22 Whereas when I run JS Radium examples (no Clojurescript and Reagent), this render function gets fired on every onMouseEnter onMouseLeave. With reagent not at all.

Does Reagent somehow block re-rendering when component state changes?

like image 322
ma2s Avatar asked Sep 02 '15 14:09

ma2s


1 Answers

I've translated the basic button Radium example to be used with Reagent:

(def Radium js/Radium)

(def styles {:base {:color "#fff"
                    ":hover" {:background "#0A8DFF"}}
             :primary {:background "#0074D9"}
             :warning {:background "#FF4136"}})

(defn button
  [data]
  (let [kind (keyword (:kind data))]
    [:button
     {:style (clj->js [(:base styles)
                       (kind styles)])}
     (:children data)]))

(def btn (Radium. (reagent/reactify-component button)))

(def rbtn (reagent/adapt-react-class btn))

(defn hello-world
  []
  [:div
   [rbtn {:kind :primary} "Hello Primary"]
   [rbtn {:kind :warning} "Hello Warning"]])

The key thing is that I converted button reagent component to a React component (using reactify-component), then passed it through Radium and then converted it back to something which I consume in reagent (using adapt-react-class).

In my example, hover works.

Hope this helps.

I've placed the working version on GitHub.

like image 51
ducky Avatar answered Oct 20 '22 03:10

ducky