在 uberjar 中订阅和添加观看

Subscribe and add-watch in uberjar

我有使用 reagent/create-class 创建的组件,它获取由 subscribe 创建的原子。我在 :component-did-mount 上添加了一个手表,以便根据请求调用组件 (js) 函数,这是由原子的变化触发的(有一个服务器往返)。它看起来有点像下面这样:

(defn editor [text issue-hints]
  (let []
    (reagent-core/create-class
     {:component-did-mount
      #(let [editor      (js/SimpleMDE.
                          (clj->js {...}))]
         (do
           ...
           (add-watch issue-hints :watch-issue-hints (show-hint (-> editor .-codemirror)))
           ...))
      :reagent-render
      (fn [this] [:textarea])})))

(defn edit-panel [text]
  (let [test (re-frame.core/subscribe [:issue-hints])]
    [box
     :class "issue-detail"
     :size "auto"
     :child [:div.issue-detail [editor text test]]]))

它在调试项目时运行良好,但是一旦 uberjar 文件是 运行,监视处理程序就永远不会被调用。对我来说最奇怪的是,如果至少添加了对订阅原子的虚拟引用,它会再次运行良好(例如 dummy @issue-hints 在与订阅相同的 let 中)。服务器往返看起来不错。

谁能给我解释一下and/or 更合理的建议fix/workaround?

看来您需要 :reagent-render 中的两个参数,而不是一个 -

:reagent-render
  (fn [text issue-hints] [:textarea])}))) ---> Not "this", but should match initial args

当您只传递一个 arg,并且没有在 component-did-mount fn 中取消引用时,它不会收到后续更改的订阅。

此外,我认为您不需要明确使用 add-watch,因为那是 re-frame 订阅为您提供的 ootb。通过使用 deref 语法 @issue-hints,只要 issue-hints 发生更改,元素就会收到通知,您应该能够从 app-db.

观察状态

如果您添加第二个参数,我猜您可以删除 add-watch,它应该会按预期工作。

这是 docs 如果您查看代码示例,您会看到参数的重复...

----- Edit: Will Form-2 work? -----

(defn editor [text issue-hints]
  (let [hints @issue-hints
        editor (js/SimpleMDE. (clj->js {...})] ;;-> This will not be dynamic, so consider moving to returned fn if necessary
    (fn [text issue-hints]
       (if hints
          [:textarea (special-hint-handler hints)]
          [:textarea]
    ))))

所以根据评论,这会给你一个 issue-hintswatcher,你可以做出相应的回应。订阅不一定需要在 DOM 上使用。