当使用Clojurescript在Reagent上阅读this post时,我尝试了不同的方法来实现timer-component
组件。然而,我的第一次尝试不起作用:
(defn timer-component []
(fn []
(let [seconds-elapsed (r/atom 0)]
(js/setTimeout #(swap! seconds-elapsed inc) 1000)
[:p (str "Expired time: " @seconds-elapsed)])))
作为调试日志语句显示仍然定期调用计时器,并且seconds-elapsed
变量仍然正确更新。但是,显示不会更新,组件始终显示"过期时间:0"。
与博客文章中的代码示例相比,我的组件交换了fn
和let
声明,这种修改似乎阻止了正确显示,但没有正确更新组件。我的期望是组件既可以更新也可以正确显示,也可以既不更新也不显示。
我的问题是为什么会发生这种情况?这是Reagent中的一个错误还是我个人滥用了API?
答案 0 :(得分:2)
您总是看到相同的值,因为每个(重新)渲染都会调用内部匿名函数。因此,seconds-elapsed
一次又一次地被绑定到一个值为0的新原子。这不是一个错误,而是Reagent应该如何工作。
您的组件是“Form-2”,并且应该在外部函数timer-component
中声明其本地状态,每个组件只调用一次。 Re-frame documentation explains different forms of Reagent components很好。
重新构建文档为试剂教程中的示例添加注释,这可能有助于澄清:
(defn timer-component []
(let [seconds-elapsed (reagent/atom 0)] ;; setup, and local state
(fn [] ;; inner, render function is returned
(js/setTimeout #(swap! seconds-elapsed inc) 1000)
[:div "Seconds Elapsed: " @seconds-elapsed])))