我正在尝试使用几乎没有经验的Clojure和Reagent,尝试制作一个简单的计时器。
(defn reset-component [t]
[:input {:type "button" :value "Reset"
:on-click #(reset! t 60)}])
(defn countdown-component []
(let [seconds-left (atom 60)]
(fn []
(js/setTimeout #(swap! seconds-left dec) 1000)
[:div.timer
[:div "Time Remaining: " (show-time @seconds-left)]
[reset-component seconds-left]])))
计时器倒计时似乎正常,直到我按下重置按钮。之后,计时器开始倒计时两倍。每次按下重置按钮,它都会更快地倒计时。
如何让计时器在页面加载时自动倒计时,但在点击重置按钮时不会倒计时更快?
答案 0 :(得分:3)
取消引用reset-component中的秒数会触发倒计时组件的重新呈现,该组件会将另一个递减器功能附加到倒计时组件。
答案 1 :(得分:2)
为了将来参考,reagent
0.6.0 +带有一个新的with-let
宏,对于需要正确"销毁"的内容非常有用,例如{{1} } / setInterval
:
clearInterval
这是该功能的官方anouncement。
请注意,从渲染函数调用(defn countdown-component []
(r/with-let [seconds-left (r/atom 60)
timer-fn (js/setInterval #(swap! seconds-left dec) 1000)]
[:div.timer
[:div "Time Remaining: " (str @seconds-left)]]
(finally (js/clearInterval timer-fn))))
也可以,但它不被视为好习惯。 (例如https://clojurians.slack.com/archives/C0620C0C8/p1495568238109060)
答案 2 :(得分:1)
我发现的解决方案是在组件函数之前使用setInterval
而不是在组件函数中使用setTimeout
:
(defn reset-component [seconds]
[:input {:type "button" :value "Reset"
:on-click #(reset! seconds 60)}])
(defn countdown-component []
(let [seconds-left (atom 60)]
(js/setInterval #(swap! seconds-left dec) 1000)
(fn []
[:div.timer
[:div "Time Remaining: " @seconds-left]
[reset-component seconds-left]])))
答案 3 :(得分:0)
你可能想要这个:
(defn reset-component [t]
[:input {:type "button" :value "Reset"
:on-click #(reset! t 60)}])
(defn countdown-component []
(let [seconds-left (atom 60)]
(js/setInterval #(swap! seconds-left dec) 1000)
(fn []
[:div.timer
[:div "Time Remaining: " (show-time @seconds-left)]
[reset-component seconds-left]])))
请注意,现在调用setInterval
仅在组件初始化时发生,而不是在呈现阶段发生。