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,