docs
docs copied to clipboard
`Astro.slots` example is not working
The example code for Astro.slots
doesn't seem to work, and I'm not sure whether the given example is wrong or the api has a bug.
The code I tested is:
---
// components/Message.astro
let html: string = '';
if (Astro.slots.has('default')) {
html = await Astro.slots.render('default', Astro.props.messages)
}
---
<Fragment set:html={html} />
---
// pages/index.astro
import Message from '../components/Message.astro'
---
<div>
<Message messages={['Hello', 'world!']}>{(messages) => messages.join(' ')}</Message>
</div>
<!--
must be renders as
<div>Hello world!</div>
-->
This example gives me an error that says message.join is not a function
.
If I have made any mistake, please let me know.
Thank you!
link to the doc: https://docs.astro.build/en/reference/api-reference/#astroslots minimal reproduction: https://codesandbox.io/s/distracted-shamir-hpxuel?file=/src/pages/index.astro
I'm confirming the behaviour in the CodeSandbox. I'm also getting messages.join is not a function
Furthermore, when I play around with variations of this, I'm getting messages is not defined
, so I think the error is less about not being able to perform the join, and more about messages
itself being undefined (and THAT's why messages.join
is not a function.)
@aFuzzyBear I think you were going to take a look at this one?
Raising an issue on the main Astro repo for this as it is likely a bug. Here’s a Stackblitz reproduction:
https://stackblitz.com/edit/github-csutf1?file=src%2Fpages%2Findex.astro,src%2Fcomponents%2FMessage.astro
We should remove this example from the docs in the meantime.
Example in the docs has been commented out. When https://github.com/withastro/astro/issues/3562 is fixed, we can go back and revive the example.
Untill then, labelled as "on hold."
Hello! An update on this, the function works as expected, however the second argument of Astro.render.slots
is an array of argument to pass, as such when trying to pass an array as a single parameter, it needs to be an item of the array:
So in this case, it needs to be the following:
html = await Astro.slots.render('default', [Astro.props.messages])
(Note the square brackets around Astro.props.messages
!)
Otherwise, every item of the array will be passed as a separate argument, that you'd use like so:
<Component>
{(hello, world) => <div>{hello}, {world}!</div>}
</Component>
Waiting on this issue, then will document as a use case for Astro.slots.render
in the reference docs.
There's a bit of an API design rough edge here. Normally, you'd only need to use Astro.slots.render
for dynamically rendering a slot. But now it's the only way to implement "slot props" in Astro. So even though you're certain you want to render a specific slot, you're now forced to use Fragment
and Astro.slots.render
for that use case.
It's also a hidden feature, and doesn't match any existing slots implementation.
Vue: Scoped slots Svelte: Slot props
I think Svelte's implementation on the component definition side would be a great alternative to Astro.slots.render
here.
<div>
<slot foo="hello" bar="word"/>
</div>
On the consuming side, I like our current "function children" interface because it matches Astro's "JSX-like" design.