reactjs - 渲染后的 Om 回调(在更改应用程序状态后聚焦元素)

标签 reactjs clojurescript om

我有一个使用组件状态和应用程序状态的文本输入元素。

React: More About Refs 所示的示例中,目标是在重新渲染后对元素调用 focus 。这里是关键部分,用React中的JS完成。

clearAndFocusInput: function() {
  // Clear the input
  this.setState({userInput: ''}, function() {
    // This code executes after the component is re-rendered
    this.refs.theInput.getDOMNode().focus();   // Boom! Focused!
  });
},

我想做类似的事情 Om 。我都没注意到

  1. Om 的 set-state! (用于更改组件状态;请参阅 docssource ),也不

  2. Om 的 update!(用于更改应用程序状态;请参阅 docssource)

提供指定回调的方法。因此,我正在寻找其他方法来导致重新渲染后发生某些事情。

这是我的例子:

(defn input-component
  [{:keys [app-state-key class-name]}]
  (fn [data owner]
    (reify
      om/IInitState
      (init-state
        [this]
        {:text (data app-state-key)})

      om/IRenderState
      (render-state
        [this state]
          (let [handle-change (handle-change-fn data app-state-key)]
            (dom/input
              #js {:ref (name app-state-key)
                   :type "text"
                   :className class-name
                   :value (:text state)
                   :onChange #(handle-change % owner state)}))))))

(defn handle-change-fn
  [app-state app-state-key]
  (fn [e owner state]
    (let [element (.-target e)
          value (.-value element)]
      (om/set-state! owner :text value)
      (if-let [value' (parse-int value)]
        (om/update! app-state app-state-key value')))))

(注意:parse-int,未显示,“清理”组件状态,使其适合应用程序状态。)

更改文本输入的组件状态不会导致其失去焦点,但改变应用程序状态则会导致其失去焦点。

我尝试过使用 core.async channel ,但这似乎没有帮助,因为我只想在重新渲染完成后发生回调。

我还尝试使用IDidUpdate,如下所示:

(defn input-component
  [{:keys [app-state-key class-name]}]
  (fn [data owner]
    (reify
      ; ...
      om/IDidUpdate
      (did-update
        [this prev-props prev-state]
        (let [e (om/get-node (.-owner this))]
          (.log js/console "did-update" e)
          (.focus e)))
      ; ...
      )))

更新:如果仅更新组件状态,则 IDidUpdate 生命周期事件触发。但是,如果应用程序状态发生变化(由于上面的 om/update!),它不会触发。

最佳答案

我想到的一个潜在解决方案是在 om/root 调用中使用 core.async 和 :tx-listen

:tx-listen 选项允许您指定一个在提供的应用程序状态更改时调用的函数 - 因此我们提供了一个写入附加有“pub”的 channel 的函数到它。

然后,当您的组件安装时,您可以使用 IWillMount 订阅该 channel 上的事件,并在 IWillUnmount 上清理它。

显然,这里有一些清理空间(特别是,您可能希望缩小组件监听的事件类型的范围) - 但它演示了基本思想。

....
(defonce changes (chan))
(defonce changes-pub (pub changes :msg-type))
....
(om/root
   (input-component {:app-state-key :input-state
                     :class-name "theClass"})
   app-state
   {:target (. js/document (getElementById "app"))
    :tx-listen (fn [tx-data root-cursor]
                 (put! changes {:msg-type :state-updated}))})

然后 - 在您的组件代码中,您可以订阅挂载时的更改,并在卸载时关闭 channel

   ...
   (reify    
      om/IWillMount
      (will-mount [_]
        (sub changes-pub :state-updated (:sub-chan (om/get-state owner)))
        (go-loop []
          (if-let [update (<! changes)]
            (let [node (om/get-node owner (name app-state-key))]
              (println "Resetting focus")
              (.focus node)
              (recur)))))  
      om/IWillUnmount
      (will-unmount [_]
        (close! (:sub-chan (om/get-state owner))))
      om/IInitState
      (init-state 
        [this]
        {:text (data app-state-key)
         :sub-chan (chan)})
      ...
      )))

关于reactjs - 渲染后的 Om 回调(在更改应用程序状态后聚焦元素),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25956705/

相关文章:

reactjs - React Facebook 登录 - 登录后 Conceal 按钮

java - Android webview 未加载本地主机服务器

javascript - 如何在 react 钩子(Hook)中创建可重用状态?

javascript - Css 过渡不适用于 React 中的条件渲染

web-services - 服务器将数据从Clojure推送到ClojureScript

clojurescript - 将不同的 React 版本与 clojurescript react 库一起使用(试剂、om、rum、quiescent)

clojure/script 将宏扩展为 'def' block 内的多个 'do'

clojure - 带联合的查询组合如何与通过 Om Next 中的 props 传递的父子树配合使用

error-handling - Clojurescript/试剂处理错误

unit-testing - 通过模拟请求使用异步 api 调用测试组件