prum icon indicating copy to clipboard operation
prum copied to clipboard

Lists of children can only be the last child of an element

Open garrett-hopper opened this issue 7 years ago • 13 comments

In Rum, I could have:

[:div
  [:h1 "alpha"]
  (map #(identity [:h1 (str %)]) (range 10))
  [:h1 "beta"]]

However, in Prum, "beta" doesn't show up. Everything works as expected if the map list is moved to the bottom.

garrett-hopper avatar Jan 21 '18 17:01 garrett-hopper

I’ll look into this later. But it could be also an issue in Hicada compiler which Prum adopted recently. If you could try to compile the snippet with Hicada directly and report back it would help to identify the source of the issue. Thanks.

roman01la avatar Jan 21 '18 17:01 roman01la

Oh wait. I just noticed that you have Hiccup inside of map fn. Most likely it is not being compiled. The reason is that Prum/Hicada doesn’t have runtime interpretation unlike Rum/Sablono. Hicada can walk into simple forms like if, let, do, cond, case, etc., but not into other function calls.

Wrap that Hiccup form with prum.compiler/html macro to force compilation.

roman01la avatar Jan 21 '18 18:01 roman01la

Is the list of h1’s rendered as expected?

roman01la avatar Jan 21 '18 18:01 roman01la

The list is being rendered as expected, but anything after it isn't rendered.

garrett-hopper avatar Jan 21 '18 18:01 garrett-hopper

How about an instance where I want a dynamic number of sub-components in the middle of other elements? (map #(identity (Component %)) (range 10)) Sometimes it doesn't make sense for those components to all be grouped in a div.

garrett-hopper avatar Jan 21 '18 18:01 garrett-hopper

A list of components is rendered as expected, bc components use html macro internally.

roman01la avatar Jan 21 '18 18:01 roman01la

Could you test now directly with Hicada?

roman01la avatar Jan 21 '18 18:01 roman01la

Apparently this:

(prum/defc Layout [_]
  [:div
   [:h1 "alpha"]
   (map #(identity [:h1 %]) (range 5))
   [:h1 "beta"]])

Results in this:

<div>
<h1>alpha</h1>
<undefined></undefined>
"0"
<undefined></undefined>
"1"
<undefined></undefined>
"2"
<undefined></undefined>
"3"
<undefined></undefined>
"4"
<h1>beta</h1>
</div>

However, a for works perfectly:

(prum/defc Layout [_]
  [:divA list of co
   [:h1 "alpha"]
   (for [i (range 5)]
     [:h1 i])
   [:h1 "beta"]])

Using map for components works, however it eliminates anything following it: (No undefined tags, but also no "beta")

(prum/defc Number [i]
  [:h1 i])

(prum/defc Layout [_]
  [:div
   [:h1 "alpha"]
   (map #(Number %) (range 5))
   [:h1 "beta"]])

This does though:

(prum/defc Number [i]
  [:h1 i])

(prum/defc Layout [_]
  [:div
   [:h1 "alpha"]
   (for [i (range 5)]
     (Number i))
   [:h1 "beta"]])

What's very strange is what this results in: (Using prum.compiler/html)

(prum/defc Layout [_]
  [:div
   [:h1 "alpha"]
   (map #(html [:h1 %]) (range 5))
   [:h1 "beta"]])

Results in:

<div>
<h1>alpha</h1>
<h1>
"0"
<h1>beta</h1>
</h1>
<h1>1</h1>
<h1>2</h1>
<h1>3</h1>
<h1>4</h1>
</div>

garrett-hopper avatar Jan 21 '18 18:01 garrett-hopper

I'm looking into Hicada now. I'm not entirely understanding how it works though.

garrett-hopper avatar Jan 21 '18 18:01 garrett-hopper

Looks like things are messed up here. I’ll take a look closer next week. Don’t worry. Thanks for helping me out with this!

roman01la avatar Jan 21 '18 19:01 roman01la

Thanks! Let me know if there's anything I can do to help.

garrett-hopper avatar Jan 21 '18 19:01 garrett-hopper

OK. So...

  • The first example is an expected behavior, bc you have to wrap Hiccup form with html macro explicitly in such cases.
  • The second one with for works bc Hicada is able to walk into some Clojure forms such as if, when, for, etc., but not function calls such as map as in the prev example
  • Example where beta is missing after (map #(Number %) (range 5)) but works fine with for seems to be a problem within Preact and how it handles iterable collections of child elements. I'll look into it (I maintain a fork of Preact with iterable children support)
  • The last one seems to have the same source of the problem as the previous issue

Now that I know where to look at, I'll dig into Preact and see what can be done there.

roman01la avatar Feb 07 '18 10:02 roman01la

Looks like it has something to do with ClojureScript's collections, not entirely sure yet. But, for example, Preact renders fine Immutable.js persistent collections.

For now the workaround is to use into-array on a sequence of elements

(prum/defc Layout [_]
  [:div
   [:h1 "alpha"]
   (->> (map #(Number %) (range 5)) into-array)
   [:h1 "beta"]])

roman01la avatar Feb 07 '18 11:02 roman01la