Added more clarification around using Astro.slots.render (#4456)

* Add an error message for when something that's not an array is passed to Astro.slots.render

* Add changeset

* Add more details
This commit is contained in:
Erika 2022-08-25 12:42:27 -03:00 committed by GitHub
parent 78334b9765
commit 47e71ae8f8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 39 additions and 7 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Added an error message when the second argument of Astro.slots.render is not an array

View file

@ -203,7 +203,7 @@ export interface AstroGlobal extends AstroGlobalPartial {
*/
has(slotName: string): boolean;
/**
* Asychronously renders this slot and returns HTML
* Asynchronously renders this slot and returns a string
*
* Example usage:
* ```astro
@ -216,6 +216,21 @@ export interface AstroGlobal extends AstroGlobalPartial {
* <Fragment set:html={html} />
* ```
*
* A second parameters can be used to pass arguments to a slotted callback
*
* Example usage:
* ```astro
* ---
* html = await Astro.slots.render('default', ["Hello", "World"])
* ---
* ```
* Each item in the array will be passed as an argument that you can use like so:
* ```astro
* <Component>
* {(hello, world) => <div>{hello}, {world}!</div>}
* </Component>
* ```
*
* [Astro reference](https://docs.astro.build/en/reference/api-reference/#astroslots)
*/
render(slotName: string, args?: any[]): Promise<string>;

View file

@ -55,10 +55,13 @@ class Slots {
#cache = new Map<string, string>();
#result: SSRResult;
#slots: Record<string, any> | null;
#loggingOpts: LogOptions;
constructor(result: SSRResult, slots: Record<string, any> | null) {
constructor(result: SSRResult, slots: Record<string, any> | null, logging: LogOptions) {
this.#result = result;
this.#slots = slots;
this.#loggingOpts = logging;
if (slots) {
for (const key of Object.keys(slots)) {
if ((this as any)[key] !== undefined) {
@ -92,11 +95,20 @@ class Slots {
if (!cacheable) {
const component = await this.#slots[name]();
const expression = getFunctionExpression(component);
if (expression) {
const slot = expression(...args);
return await renderSlot(this.#result, slot).then((res) =>
res != null ? String(res) : res
if (!Array.isArray(args)) {
warn(
this.#loggingOpts,
'Astro.slots.render',
`Expected second parameter to be an array, received a ${typeof args}. If you're trying to pass an array as a single argument and getting unexpected results, make sure you're passing your array as a item of an array. Ex: Astro.slots.render('default', [["Hello", "World"]])`
);
} else {
if (expression) {
const slot = expression(...args);
return await renderSlot(this.#result, slot).then((res) =>
res != null ? String(res) : res
);
}
}
}
const content = await renderSlot(this.#result, this.#slots[name]).then((res) =>
@ -146,7 +158,7 @@ export function createResult(args: CreateResultArgs): SSRResult {
props: Record<string, any>,
slots: Record<string, any> | null
) {
const astroSlots = new Slots(result, slots);
const astroSlots = new Slots(result, slots, args.logging);
const Astro = {
__proto__: astroGlobal,