This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-07-06
Channels
- # aleph (1)
- # announcements (29)
- # babashka (39)
- # beginners (52)
- # cider (3)
- # cljsrn (19)
- # clojure (167)
- # clojure-europe (15)
- # clojure-nl (2)
- # clojure-uk (62)
- # clojurescript (13)
- # community-development (8)
- # cursive (5)
- # datomic (10)
- # introduce-yourself (1)
- # java (10)
- # jobs (12)
- # jobs-discuss (1)
- # kaocha (2)
- # lsp (6)
- # luminus (1)
- # malli (15)
- # meander (3)
- # music (1)
- # nrepl (2)
- # off-topic (91)
- # pathom (4)
- # reagent (21)
- # reitit (10)
- # sci (5)
- # shadow-cljs (17)
- # spacemacs (3)
- # sql (7)
- # tools-deps (40)
- # utah-clojurians (2)
- # xtdb (7)
What is the recommended approach for passing a lot of arguments to a reagent component? Right now I pass them as a normal function
[:div
(navbar)
[:h1 "Title"]
[multiargument-component
geolocation
net-worth-thousands
(.parseInt js/Number (get @app-state "age"))
annual-savings
withdrawal-rate
annual-return]]
This components' arguments get passed down to several other components, where I need to keep track of their arguments.
Sometimes i might change annual-savings
to monthly-savings
, but then i need to update every intermediate component in the component tree until i reach the component that will actually implement the change.
So i'm thinking that it would make sense to pass down a map instead with all the needed arguments something like this:
[:div
(navbar)
[:h1 "Title"]
[multiargument-component
{:geolocation geolocation
:net-worth-thousands net-worth-thousands
:age (.parseInt js/Number (get @app-state "age"))
:annual-savings annual-savings
:withdrawal-rate withdrawal-rate
:annual-return annual-return}]]
Then when i make a change i only need to change the annual savings in the topmost component and then in the child component that consumes the argument.
The con would be that all child components would get all arguments, which might cause too many unneeded arguments to be passed around.. but then again it is a map, so AFAIK it would not impact performance, since it is only passing down the reference.
What would you recommend?However there’s a problem with passing down many props. Performance wise you will have many re-renderings even if you don’t use the “props that change” in your component
(def counter (r/atom 0))
(defn counter-component
[{:keys [label]}]
(prn "re-rendering")
[:p label])
(defn wrapper []
[:div
[:button
{:on-click #(swap! counter inc)}
"Increase counter"]
[counter-component {:counter @counter
:label "counter label"}]])
(defn main-view
[]
[wrapper])
you will notice that although the counter is never used in counter-component, you will get the “re-rendering” logs every time the counter increases
try to then remove the counter key from the map and you see that the component never re-renders
To wrap it up just make sure that you pass as params only what the component actually needs vs the world 🙂
Note that calling a view function != re-rendering.
counter-component
function will be re-executed. But the component will not be re-rendered because the Hiccup vector [:p label]
is the same.
Indeed. But I usually don't care about shallow trees with few leaves - doesn't matter if it's 5 ms or 10 ms. I have never measured anything like it though - I only measure when I perceive some delay that I would like to get rid of.