组件中指定的Ratom无法更新该组件?

时间:2016-07-16 19:41:39

标签: clojurescript reagent

刚开始使用Reagent。我有一个按钮,其# # summarize the data for the plot # trip_freq_plot <- trip_freq %>% group_by(DAY, START_TIME) %>% summarize(Cnt = sum(Freq)) 值导致CPU密集型函数运行;返回需要很长时间。我想更新按钮本身的文本以通知用户可能必须等待,因此我定义了一个指定按钮文本的ratom,然后在函数运行时我:on-click

如果我在我的按钮组件功能之外定义了ratom,但是如果我通过reset!在组件功能中定义了ratom,或者如果我let在顶层的ratom,则无法工作在组件功能中。也就是说,如果我取消注释下面的第一个注释行,或取消注释reset!的两行,则按钮文本无法更改。难道我做错了什么?这是预期的行为吗?关于ratoms和DOM更新的一般规则适用于什么?

let

(不相关,但为了澄清:我使用(def label (reagent.core/atom "Make chart")) (defn chart-button [normal-label running-label] ; (reset! label normal-label) ; reset globally-defined ratom ; (let [label (reagent.core/atom normal-label)] ; use local ratom [:button {:on-click (fn [] (reset! label running-label) (js/setTimeout (fn [] (cpu-intensive-function) (reset! label normal-label)) 10)) } @label] ;) ) ... [chart-button "make chart" "running..."] ... 技巧described here导致DOM更新,尽管长时间运行的功能会阻止浏览器更新DOM该功能正在运行。)

1 个答案:

答案 0 :(得分:2)

您的问题是,每次组件需要(重新)呈现时,您的函数chart-button都会被调用。例如,在您的本地重置示例中,有人点击该按钮,您的label将重置为running-label。试剂检测到此更改并调用您的chart-button函数,以查看新呈现的按钮应该是什么样的,此时您的第一次重置更改又回来了。 let版本有类似的问题。

有几种方法可以处理Reagent中的本地状态。最简单的方法是从组件返回一个函数而不是向量,如本例所示。

(defn timer-component []
  (let [seconds-elapsed (r/atom 0)]
    (js/setInterval #(swap! seconds-elapsed inc) 1000)
    (fn []
      [:div
       "Seconds Elapsed: " @seconds-elapsed])))

基本上在Reagent中,您的组件可以是渲染函数,也可以是返回渲染函数的函数。在上面的例子中,我们使用一个闭包来设置一些局部状态,然后返回一个使用该状态的渲染函数。每次seconds-elapsed递增时,再次调用内部函数并重新呈现组件。

另一种方式更复杂,但可能会帮助你更有意义。您可以使用create-class而不是使用函数作为组件来完全控制组件生命周期。