-
Notifications
You must be signed in to change notification settings - Fork 80
Description
What version of @astrojs/compiler
are you using?
2.10.3
What package manager are you using?
npm
What operating system are you using?
Linux
Describe the Bug
Using JSX in an attribute value causes crash with an unhelpful error message.
Example
The following component:
---
// List.astro
// Is it possible for items to be a list of *rendered* Astro components?
const { items } = Astro.props;
---
<ol class="mylist">
{items.map((item) => <li class="mylist-item">{item}</li>)}
</ol>
When used in the following way:
---
const items = [
{"href": "https://astro.build", "title": "Homepage", "body": "Visit the homepage."},
{"href": "https://astro.new", "title": "New project", "body": "Try Astro."},
];
---
<List items={
items.map((item) => (
<div class="card">
<a href={item.href}>
<h2>{item.title}</h2>
<p>{item.body}</p>
</a>
</div>
))}
</List>
Causes a crash.
Even just the following use of the <List>
component would cause a crash:
<List items={[<p>Hello</p>, <p>World</p>]} />
Expected result
<ol class="mylist">
<li class="mylist-item">
<div class="card">
<a href="https://astro.build>
<h2>Homepage</h2>
<p>Visit the homepage.</p>
</a>
</div>
</li>
<li class="mylist-item">
<div class="card">
<a href="https://astro.new>
<h2>New project</h2>
<p>Try astro.</p>
</a>
</div>
</li>
</ol>
Or in the case of the simple example
<ol class="mylist">
<li class="mylist-item">
<p>Hello</p>
</li>
<li class="mylist-item">
<p>World</p>
</li>
</ol>
Notes
Frankly, this works:
{(() => {
const listItems = items.map((item) => (
<div class="card">
<a href={item.href}>
<h2>{item.title}</h2>
<p>{item.body}</p>
</a>
</div>
));
return <List items={listItems} />;
})()}
This works too:
{(() => {
const examples = [<p>Hello</p>, <p>World</p>];
return <List items={examples} />;
})()}
But this doesn't:
{(() => {
return <List items={[<p>Hello</p>, <p>World</p>]} />;
})()}
Use case
I want to make the <List>
component accepts a list of renderable elements. It will wrap each element with a li.mylist-item
, and then wrap the whole thing in ol.mylist
.
When I use <List>
, I just want to pass the list of items that will go inside the <li>
. I don't need to know about the fact that each <li>
will have .mylist-item
, that's just an implementation detail of <List>
.
Link to Minimal Reproducible Example
https://stackblitz.com/edit/github-yujqde?file=src%2Fpages%2Findex.astro
A more elaborate example
I originally framed this as a question of migrating my React component to Astro on the Discord #general and #support channels:
- The React example I want to migrate to Astro: https://stackblitz.com/edit/vitejs-vite-bhlcnx?file=src%2FApp.tsx
- Problem definition: https://stackblitz.com/edit/withastro-astro-ck2pq8?file=src%2Fpages%2Findex.astro
- What I ended up doing: https://stackblitz.com/edit/withastro-astro-yqqbws?file=src%2Fpages%2Findex.astro
See also: https://discord.com/channels/830184174198718474/1297291875002355834