-
-
Notifications
You must be signed in to change notification settings - Fork 716
Macros WIP
Tim Gilbert edited this page Apr 4, 2015
·
6 revisions
We haven't formalised any macros yet, but we're making a collection of useful snippets here ...
Credit: @rsslldnphy
You might need to write this component:
(defn user-details
[]
(let [user (subscribe [:current-user])]
(fn [] ;; sometimes you forget the extra function layer
[:div
[:h1 (:name @user)] ;; easy to forget the @ on user
[:p (:bio @user)]]))
Some common pitfalls are noted in comments.
Here's an alternative way:
(defn user-details
[]
(with-subs [user [:current-user]] ;; say what subscriptions you want here
[:div
[:h1 (:name user)] ;; look - using 'user' with no leading @
[:p (:bio user)]]))
Here's how you do it:
(defn- to-sub
[[binding sub]]
`[~binding (re-frame.core/subscribe ~sub)])
(defn- to-deref
[binding]
`[~binding (deref ~binding)])
(defmacro with-subs
[bindings & body]
`(let [~@(apply concat (map to-sub (partition 2 bindings)))]
(fn []
(let [~@(apply concat (map to-deref (take-nth 2 bindings)))]
~@body))))
There's another subtle reason to like this macro: If ever you subscribe
in a component, but then never use the result of the subscription, you'll have created a small memory leak.
(def my-component
[]
(let [name (subscribe [:a :b])] ;; subscribe here
(fn []
[:div "hello"]))) ;; oops I never used @name in the renderer
The fix is obviously to remove this unused subscription. But because this macro explicitly "derefs" all subscription results (eg; name above), in the renderer, there'll be no memory leak. But you'll still have a slightly harmless bug, because you have declared a subscription you never use.
Deprecated Tutorials:
Reagent: