为什么 Radium 不适用于 Reagent (Clojurescript)?

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

我正试图开始工作FormidableLabs/radium · GitHub with reagent-project/reagent · GitHub,但我走到了死胡同。

我可以通过 "hacking" 试剂函数 create-class 像这样让它部分工作(它几乎和原来的一样,我只是添加了 js/Radium 包装器)。

(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))

然后我为组件做了这样的功能

(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"])}))

我在其他一些试剂渲染函数的某处使用它,例如:[radium/radium]

我正在研究 Radium 代码以找出问题所在。 好兆头是 Radium 正确地将 onMouseEnter onMouseLeave 道具分配给组件并将组件的 :hover 状态设置为 true。

这被正确触发:https://github.com/FormidableLabs/radium/blob/master/modules/resolve-styles.js#L412

问题是 render 函数,它应该根据新状态(由 Radium 更改)重新渲染组件,根本没有被触发。 这个 render 函数: https://github.com/FormidableLabs/radium/blob/master/modules/enhancer.js#L22 而当我 运行 JS Radium 示例(没有 Clojurescript 和 Reagent)时,此渲染函数会在每个 onMouseEnter onMouseLeave 上触发。完全没有试剂。

当组件状态改变时,Reagent 是否以某种方式阻止重新渲染?

我已经翻译了与 Reagent 一起使用的基本按钮 Radium 示例:

(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"]])

关键是我将 button 试剂组件转换为 React 组件(使用 reactify-component),然后通过 Radium 传递它,然后将其转换回我在试剂中消耗的东西(使用 adapt-react-class).

在我的示例中,hover 有效。

希望这对您有所帮助。

我已将工作版本放在 GitHub