prum
prum copied to clipboard
Lists of children can only be the last child of an element
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.
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.
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.
Is the list of h1’s rendered as expected?
The list is being rendered as expected, but anything after it isn't rendered.
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.
A list of components is rendered as expected, bc components use html macro internally.
Could you test now directly with Hicada?
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>
I'm looking into Hicada now. I'm not entirely understanding how it works though.
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!
Thanks! Let me know if there's anything I can do to help.
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 asif
,when
,for
, etc., but not function calls such asmap
as in the prev example - Example where
beta
is missing after(map #(Number %) (range 5))
but works fine withfor
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.
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"]])