我正在编写一个Clojurescript应用程序,使用Reagent使我的组件被反应。
我有一个简单的问题。我应该
在tutorial中,他们使用后者选项,但是在尝试保持我的功能纯洁时,我选择了前者。
我是否正确地说使用它们作为全局变量(除了在定义组件输入时不那么冗长)还会阻止重新呈现未使用原子状态的整个父组件?
答案 0 :(得分:8)
我更喜欢将鼠标传递给组件。 重新框架越来越受欢迎https://github.com/Day8/re-frame
传递一个鼠标并不会使你的功能更加纯净,原子仍然会受到副作用。它确实使您的组件更加灵活和可重用,因为它们定义了它们的依赖关系。
无论是引用全局数据库还是传入数据库,它都不会直接影响重新呈现。渲染时间的信号图是根据矢量内部的deref的出现构建的,它并不关心ratom来自何处。但是,通过创建反应可以提高效率。
(defn my-component []
(let [x (reaction (:x @db)]
(fn []
[:div @x]))
此组件仅在以下情况下重新渲染:x更改(而不是db中的任何更改。创建反应可能会变得乏味,这是重新构建的吸引力之一。
(ns whip.view.reactions
(:require [reagent.core :as reagent]
[devcards.core :refer-macros [defcard-rg deftest]])
(:require-macros [reagent.ratom :refer [reaction]]))
(def a (reagent/atom {:x 100 :y 200})) (def b (reaction (:x @a)))
(def c (reaction (+ @b 10)))
(defn view-c []
(prn "Rendering view-c") [:div
[:div @c]
[:button {:on-click (fn [e] (swap! a update :x inc))} "inc x"]
[:button {:on-click (fn [e] (swap! a update :y inc))} "inc y"]])
(defcard-rg reaction-example [view-c])
反应是表达数据流的一种非常简洁的方式。在这里,您将从包含x的ratom开始 和y值。然后构建一个只观察x值的反应b。接下来,引入另一个观察b和10之和的反应c。然后创建一个反应性地呈现c的组件。请注意,单击“inc x”按钮时,视图将更新为应用表达式的结果。单击“inc y”按钮时,没有任何反应。检查控制台,确认只有在单击“inc x”时才会打印“Rendering view-c”消息。这是一件非常好的事情,因为视图不以任何方式依赖于y。如果你在视图中deref a而不是c,即使y改变了它也会被重新渲染。 试剂通过requestAnimationFrame对反应和ratoms作出反应。因此,改变许多大鼠和依赖它们的反应只会导致一个渲染阶段。
答案 1 :(得分:6)
如果你让你的组件接受原子作为参数,那么你可以使它们更容易重复使用并且更容易测试。
如果您选择将整个应用程序状态保存在单个atom中,然后使用游标将其传递给子组件,则尤其如此。
;; setup a single instance of global state
(defonce app-state
(reagent/atom {:foo 0 :bar 0})
;; define a generic counter component that knows
;; nothing about the global state
(defn counter
[count]
[:div
[:button {:onclick #(swap! count inc) "+"]
[:span @count]])
;; define counter components and give them access to
;; specific context within the global state
(defn app
[state]
[counter (reagent/cursor app-state [:foo])]
[counter (reagent/cursor app-state [:bar])])
如果您决定将试剂与Re-frame一起使用,您甚至可以更进一步。重新框架鼓励您使用看起来像这样的特定架构来构建您的应用程序。
app-db > subscriptions
^
handlers v
^
events < components
不是直接编写组件并将它们直接连接到全局原子(app-db
),而是编写subscriptions
,它们只是从{{1}中选择/查询某些数据的函数。并在app-db
发生更改时将其传递给组件。
然后,组件创建app-db
而不是直接与app-db
混淆的组件,而events
只是描述组件意图的小块数据。
这些事件将发送到handlers
,这些函数将event
和当前app-db
作为参数并返回新的app-db
。然后替换现有的app-db
,触发订阅者将数据传递给组件,依此类推。
如果你发现你的Reagent项目有点纠结并且Re-frame readme是一个很好的阅读,无论你是否决定使用它,它绝对有用。