clojurescriptreagenthiccup

What is the preferred syntax for nesting a reagent hiccup element that is returned from a function?


Given a function to return an element:

(defn title []
  [:h1 "Hello World"])

What is the preferred way of nesting this inside another component?

I've seen it done in a tutorial by wrapping the function call in a vector:

[:div {:class "app"}
  [title]]

but this seemed a little weird to me as the return value of title is a vector itself and so would expand to [[:h1 "Hello World"]]. What happens to the outer vector?

It also works to just evaluate the function inline:

[:div {:class "app"}
  (title)]

but I'm not sure if this is a good idea given the mix of parens and square brackets it could be hard to read.

Any opinions?


Solution

  • This is more specific to reagent than to hiccup(ish html-generators) -- it may or may not work with different frameworks or hiccup on the server-side.

    Reagent takes a function in place of a "tag" and treats it as a react component. Note that [title] is not calling the function. It's a vector, that holds the reference to the function.

    So the difference here is, whether you want title being treated like a component (with all that comes with it (when using [title])) or if you just call (title) there and it will place the result right there in the vector.

    There is a whole tutorial page dedicated to that:

    So, which variation of greet-family (square vs round) should I choose, and why?

    The answer to "which?" is easy: you almost certainly want the square version. "why?" takes more explanation ...

    First off, let's acknowledge that both variations will ultimately produce the same DOM, so in that respect they are the same.

    Despite this identical outcome, they differ in one significant way:

    1. the square version will create each greet child as a distinct React component, each with its own React lifecycle, allowing them to re-render independently of siblings.
    2. The round version causes the greet hiccup for all children to be incorporated into the hiccup returned by the parent, forming one large data structure, parent and children all in together. So, each time the parent re-renders, all the greet children are effectively re-rendered too. React must then work out what, in this tree, has changed.

    As a result, the square version will be more efficient at "re-render time". Only the DOM which needs to be re-rendered will be done. At our toy scale in this tutorial it hardly matters but, if greet was a more substantial child component, this gain in efficiency could be significant.