Почему Radium не работает с реагентом (Clojurescript)?

Я пытался заставить работать https://github.com/FormidableLabs/radium с реагентом-проектом / реагентом · GitHub, но я зашел в тупик.

Я смог заставить его работать частично, взломав функцию реагента 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).
  • Медиа-запрос также работает, но только при первом рендере, он не реагирует динамически при изменении размера экрана.
  • :hover :focus :active не работает вообще

Я копался в коде Radium, чтобы выяснить, что не так. Хорошим знаком было то, что Radium правильно назначает onMouseEnteronMouseLeave реквизит к компоненту и наборы :hover состояние компонента до истины.

Это правильно запускается: 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), эта функция рендера запускается на каждом onMouseEnteronMouseLeave, С реагентом совсем нет.

Reagent как-то блокирует повторный рендеринг при изменении состояния компонента?

1 ответ

Решение

Я перевел основной пример кнопки Radium для использования с 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"]])

Главное, что я преобразовал button компонент реагента к компоненту React (используя reactify-component), затем пропустил его через радий, а затем преобразовал обратно во что-то, что я потребляю в реагенте (используя adapt-react-class).

В моем примере hover работает.

Надеюсь это поможет.

Я разместил рабочую версию на GitHub.

Другие вопросы по тегам