Eric Auld
Eric Auld

Reputation: 1244

Why need to return a function in Reagent component?

From the Reagent introduction, a simple timer component:

(defn timer-component []
  (let [seconds-elapsed (r/atom 0)]
    (fn []
      (js/setTimeout #(swap! seconds-elapsed inc) 1000)
      [:div
       "Seconds Elapsed: " @seconds-elapsed])))

and below it reads

The previous example also uses another feature of Reagent: a component function can return another function, that is used to do the actual rendering. This function is called with the same arguments as the first one.

This allows you to perform some setup of newly created components without resorting to React’s lifecycle events.

Can someone remind me of the underlying principle here? Why do we need this anonymous function? Why not just

(defn timer-component []
  (let [seconds-elapsed (r/atom 0)]
    (js/setTimeout #(swap! seconds-elapsed inc) 1000)
    [:div
     "Seconds Elapsed: " @seconds-elapsed])))

Upvotes: 1

Views: 654

Answers (2)

Eric Auld
Eric Auld

Reputation: 1244

Tl;dr: The anonymous function that is returned is the render method, which every component must have. You can elide the anonymous function if you use the with-let macro in Reagent.

The indispensable part of a React component is a render function, which takes a single object argument and returns a React element. The difference between render and the component constructor is that, while both methods are called upon construction, render is called on each update. (For instance, if someone calls the setState method of the component).

In the above example, the difference between the inner, anonymous function and the outer timer-component function is the same as between render and the constructor. Notice that the anonymous function closes over the variables bound in the let clause, which allows it to be stateful. If timer-component itself were the render function, then it would be called on every update, and seconds-elapsed would be endlessly reset to zero.

See the doc on the Reagent repo called "Creating Reagent Components".

Upvotes: 0

SuperJumbo
SuperJumbo

Reputation: 541

From what I remember, Reagent calls timer-component every time it wants to render - potentially setting up the same piece of state (seconds-elapsed) over and over again.

By returning that anonymous function instead, it tells Reagent "use this to render timer-component". This way your state setup is separated from rendering, and like your doco quote says, its a way to perform state setup without using Reacts lifecycle events.

Hope that makes sense

Upvotes: 4

Related Questions