From 47e71ae8f8735149facb34ce63d4d582f0dfd32e Mon Sep 17 00:00:00 2001 From: Erika <3019731+Princesseuh@users.noreply.github.com> Date: Thu, 25 Aug 2022 12:42:27 -0300 Subject: [PATCH] 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 --- .changeset/unlucky-otters-end.md | 5 +++++ packages/astro/src/@types/astro.ts | 17 ++++++++++++++++- packages/astro/src/core/render/result.ts | 24 ++++++++++++++++++------ 3 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 .changeset/unlucky-otters-end.md diff --git a/.changeset/unlucky-otters-end.md b/.changeset/unlucky-otters-end.md new file mode 100644 index 0000000000..8ad26bc694 --- /dev/null +++ b/.changeset/unlucky-otters-end.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Added an error message when the second argument of Astro.slots.render is not an array diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index 58fd779806..19aa85695a 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -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 { * * ``` * + * 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 + * + * {(hello, world) =>
{hello}, {world}!
} + *
+ * ``` + * * [Astro reference](https://docs.astro.build/en/reference/api-reference/#astroslots) */ render(slotName: string, args?: any[]): Promise; diff --git a/packages/astro/src/core/render/result.ts b/packages/astro/src/core/render/result.ts index 32dcdd9160..dc5be4a079 100644 --- a/packages/astro/src/core/render/result.ts +++ b/packages/astro/src/core/render/result.ts @@ -55,10 +55,13 @@ class Slots { #cache = new Map(); #result: SSRResult; #slots: Record | null; + #loggingOpts: LogOptions; - constructor(result: SSRResult, slots: Record | null) { + constructor(result: SSRResult, slots: Record | 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, slots: Record | null ) { - const astroSlots = new Slots(result, slots); + const astroSlots = new Slots(result, slots, args.logging); const Astro = { __proto__: astroGlobal,