Анимационный стол Anzer с rc-animate в приложении re-frame

Я пытаюсь воссоздать пример в http://react-component.github.io/table/examples/animation.html чтобы добавить анимацию в таблицу в приложении перекадровки. Таблица отображается с использованием antizer, который является библиотекой ClojureScript для компонентов реагирования Ant Design. Для анимации я пытаюсь использовать rc-animate (как в примере), который является библиотекой JavaScript. Чтобы интегрировать rc-animate, я следовал официальному руководству по Webpack и создал src/js/index.js файл:

import Animate from 'rc-animate';
window.Animate = Animate;

мой project.clj является:

(defproject ant-table-animation "0.1.0-SNAPSHOT"
  :dependencies [[org.clojure/clojure "1.8.0"]
                 [org.clojure/clojurescript "1.10.238"]
                 [reagent "0.8.1"]
                 [re-frame "0.10.5" :exclusions [reagent]]
                 [antizer "0.3.1"]]

  :plugins [[lein-cljsbuild "1.1.7"]]

  :min-lein-version "2.5.3"

  :source-paths ["src/clj" "src/cljs"]

  :clean-targets ^{:protect false} ["resources/public/js/compiled" "target"]

  :figwheel {:css-dirs ["resources/public/css"]}

  :profiles
  {:dev
   {:dependencies [[binaryage/devtools "0.9.10"]
                   [cider/piggieback "0.3.9"]
                   [figwheel-sidecar "0.5.16"]
                   [day8.re-frame/re-frame-10x "0.3.3"]]

    :plugins      [[lein-figwheel "0.5.16"]]}
   :prod { }
   }

  :cljsbuild
  {:builds
   [{:id           "dev"
     :source-paths ["src/cljs"]
     :figwheel     {:on-jsload "ant-table-animation.core/mount-root"}
     :compiler     {:closure-defines {re-frame.trace.trace_enabled_QMARK_ true}
                    :main                 ant-table-animation.core
                    :output-to            "resources/public/js/compiled/app.js"
                    :output-dir           "resources/public/js/compiled/out"
                    :asset-path           "js/compiled/out"
                    :source-map-timestamp true
                    :preloads             [devtools.preload, day8.re-frame-10x.preload]
                    :external-config      {:devtools/config {:features-to-install :all}}
                    :infer-externs true
                    :npm-deps false
                    :foreign-libs [{:file "dist/index_bundle.js"
                                    :provides ["rc-animate" "rc-animate-child"]
                                    :global-exports {rc-animate Animate
                                                 rc-animate-child AnimateChild}}]
                    }}

    {:id           "min"
     :source-paths ["src/cljs"]
     :compiler     {:main            ant-table-animation.core
                    :output-to       "resources/public/js/compiled/app.js"
                    :optimizations   :advanced
                    :closure-defines {goog.DEBUG false}
                    :pretty-print    false}}


    ]}
  )

и в моем views.cljs Я пытаюсь визуализировать таблицу следующим образом:

(ns ant-table-animation.views
  (:require
   [re-frame.core :as re-frame]
   [ant-table-animation.subs :as subs]
   [ant-table-animation.events :as events]
   [antizer.reagent :as ant]
   [reagent.core :as reagent]
   [rc-animate]
   ))

(.log js/console rc-animate)

(defn AnimateBody
  [props]
  (.createElement
    js/React
    rc-animate
    (.assign js/Object #js {:transitionName "move", :component "tbody"} props)))

(.log js/console AnimateBody)

(defn orders
  []
  (let [orders @(re-frame/subscribe [::subs/orders])
        width 80]
    [ant/table
     {:columns
      [{:title "Product Name" :dataIndex :product :width width}
       {:title "Quantity" :dataIndex :quantity :width width}
       {:title "Unit Price" :dataIndex :price :width width}
       {:title "Actions" :dataIndex "actions" :width width
        :render
        #(reagent/as-element
          [ant/button
           {:icon "delete" :type "danger"
            :on-click
            (fn []
              (re-frame/dispatch [::events/order-deleted (.-product %2)]))}])}]
      :dataSource orders
      :size "small"
      :components {:body {:wrapper AnimateBody}}
      :pagination {:page-size 20}
      :scroll {:y 300}}]))

(defn main-panel []
  (let [name (re-frame/subscribe [::subs/name])]
    [:div
     [:h1 "Hello from " @name]
     [orders]
     ]))

Я совсем не уверен в

(defn AnimateBody
  [props]
  (.createElement
    js/React
    rc-animate
    (.assign js/Object #js {:transitionName "move", :component "tbody"} props)))

эквивалентно строке из примера

const AnimateBody = props => <Animate transitionName="move" component="tbody" {...props} />;

Таблица отображается правильно, но когда я пытаюсь удалить строку, происходит сбой со следующей ошибкой:

react-dom.development.js:55 Uncaught Error: Unable to find node on an unmounted component.
at invariant (react-dom.development.js:55)
at findCurrentFiberUsingSlowPath (react-dom.development.js:4256)
at findCurrentHostFiber (react-dom.development.js:4266)
at findHostInstance (react-dom.development.js:17676)
at Object.findDOMNode (react-dom.development.js:18145)
at AnimateChild.transition (AnimateChild.js:83)
at AnimateChild.componentWillLeave (AnimateChild.js:70)
at performLeave (Animate.js:339)
at Array.forEach (<anonymous>)
at Animate.componentDidUpdate (Animate.js:188)
at commitLifeCycles (react-dom.inc.js:15386)
at commitAllLifeCycles (react-dom.inc.js:16646)
at HTMLUnknownElement.callCallback (react-dom.inc.js:143)
at Object.invokeGuardedCallbackDev (react-dom.inc.js:193)
at invokeGuardedCallback (react-dom.inc.js:250)
at commitRoot (react-dom.inc.js:16800)
at completeRoot (react-dom.inc.js:18192)
at performWorkOnRoot (react-dom.inc.js:18120)
at performWork (react-dom.inc.js:18024)
at performSyncWork (react-dom.inc.js:17996)
at requestWork (react-dom.inc.js:17884)
at scheduleWork (react-dom.inc.js:17689)
at Object.enqueueForceUpdate (react-dom.inc.js:11855)
at Object.Component.forceUpdate (react.inc.js:479)
at reagent$impl$batching$run_queue (batching.cljs?rel=1541330682770:39)
at Object.flush_queues (batching.cljs?rel=1541330682770:86)
at Object.run_queues (batching.cljs?rel=1541330682770:76)
at batching.cljs?rel=1541330682770:63
at re_frame_10x.cljs?rel=1541164419576:125

Также указано, что:

The above error occurred in the <Animate> component:
in Animate (created by ant_table_animation.views.animateBody)
in ant_table_animation.views.animateBody (created by BaseTable)
in table (created by BaseTable)
in BaseTable (created by Connect(BaseTable))
in Connect(BaseTable) (created by BodyTable)
in div (created by BodyTable)
in BodyTable (created by ExpandableTable)
in div (created by ExpandableTable)
in div (created by ExpandableTable)
in div (created by ExpandableTable)
in ExpandableTable (created by Connect(ExpandableTable))
in Connect(ExpandableTable) (created by Table)
in Provider (created by Table)
in Table (created by LocaleReceiver)
in LocaleReceiver (created by Table)
in div (created by Spin)
in AnimateChild (created by Animate)
in div (created by Animate)
in Animate (created by Spin)
in Spin (created by Table)
in div (created by Table)
in Table (created by ant_table_animation.views.orders)
in ant_table_animation.views.orders (created by    ant_table_animation.views.main_panel)
in div (created by ant_table_animation.views.main_panel)
in ant_table_animation.views.main_panel

Я новичок в Clojure и знаю еще меньше о React; вот где я оказался после недели попыток, но теперь я чувствую себя застрявшим. Я загрузил свой проект в github для тех, кто хотел бы попробовать.

1 ответ

Решение

Unable to find node on an unmounted component error происходило из-за проблем с версией React. Я смог справиться с этим, явно используя версию React, используемую rc-animate библиотека - 16.5.2 по моему project.clj:

...             
[reagent "0.8.1" :exclusions [cljsjs/react cljsjs/react-dom [cljsjs/react-dom-server]]]
[cljsjs/react "16.5.2-0"]
[cljsjs/react-dom "16.5.2-0"]
[cljsjs/react-dom-server "16.5.2-0"]
    ...
[antizer "0.3.1" :exclusions [cljsjs/react cljsjs/react-dom [cljsjs/react-dom-server]]]]
    ...

Для правильного определения AnimateBody компонент, который я должен был использовать комбинацию reagent/adapt-react-class, reagent/as-element а также reagent/reactify-component, Конкретно по моему views.cljs Я определяю компонент как:

(def animate (reagent/adapt-react-class rc-animate))
(def animateBody
  (fn [props]
    (reagent/as-element [animate (assoc props :transition-name "move" :component "tbody")])))

а затем передать его ant/table компонент с:

...
:components {:body {:wrapper (reagent/reactify-component animateBody)}}
...
Другие вопросы по тегам