From b30ec9ec5360e8eb99b4aa68bc2f35265a77d702 Mon Sep 17 00:00:00 2001 From: gimenes Date: Wed, 24 Jul 2024 15:56:45 -0300 Subject: [PATCH 1/9] async rendering --- deno.json | 2 +- htmx/sections/Deferred.tsx | 31 ++-- utils/{deferred.tsx => deferred.ts} | 7 +- website/handlers/fresh.ts | 3 +- website/manifest.gen.ts | 14 +- website/mod.ts | 5 +- website/sections/Rendering/Deferred.tsx | 7 +- website/sections/Rendering/Lazy.tsx | 145 ++++++++++++++++++ website/sections/Rendering/SingleDeferred.tsx | 109 +------------ 9 files changed, 178 insertions(+), 145 deletions(-) rename utils/{deferred.tsx => deferred.ts} (51%) create mode 100644 website/sections/Rendering/Lazy.tsx diff --git a/deno.json b/deno.json index bf11c67ee..7977979b2 100644 --- a/deno.json +++ b/deno.json @@ -9,7 +9,7 @@ "std/": "https://deno.land/std@0.204.0/", "partytown/": "https://deno.land/x/partytown@0.4.8/", "deco-sites/std/": "https://denopkg.com/deco-sites/std@1.26.7/", - "deco/": "https://cdn.jsdelivr.net/gh/deco-cx/deco@1.78.0/" + "deco/": "https://cdn.jsdelivr.net/gh/deco-cx/deco@30aa5339af59f53d5452b29eebde196a1df66a16/" }, "lock": false, "tasks": { diff --git a/htmx/sections/Deferred.tsx b/htmx/sections/Deferred.tsx index ce6379477..0c3401765 100644 --- a/htmx/sections/Deferred.tsx +++ b/htmx/sections/Deferred.tsx @@ -2,7 +2,7 @@ import type { Section } from "deco/blocks/section.ts"; import { useSection } from "deco/hooks/useSection.ts"; import { asResolved, isDeferred } from "deco/mod.ts"; import { AppContext } from "../mod.ts"; -import { renderSection, shouldForceRender } from "../../utils/deferred.tsx"; +import { shouldForceRender } from "../../utils/deferred.ts"; /** * @titleBy type @@ -10,7 +10,8 @@ import { renderSection, shouldForceRender } from "../../utils/deferred.tsx"; */ interface Load { type: "load"; - /** @hide true */ + + // TODO: @gimenes add delay delay?: number; } @@ -34,19 +35,18 @@ interface Intersect { export interface Props { sections: Section[]; - /** @hide true */ - fallbacks?: Section[]; + fallback?: Section; trigger?: Load | Revealed | Intersect; loading?: "lazy" | "eager"; } const Deferred = (props: Props) => { - const { sections, loading, trigger } = props; + const { sections, loading, trigger, fallback } = props; if (loading === "eager") { return ( <> - {sections.map(renderSection)} + {sections.map(({ Component, props }) => )} ); } @@ -61,16 +61,15 @@ const Deferred = (props: Props) => { } return ( - <> -
- {props.fallbacks?.map(renderSection)} - +
+ {fallback && } +
); }; diff --git a/utils/deferred.tsx b/utils/deferred.ts similarity index 51% rename from utils/deferred.tsx rename to utils/deferred.ts index dd10cb224..2a555cfb6 100644 --- a/utils/deferred.tsx +++ b/utils/deferred.ts @@ -1,10 +1,5 @@ -import { Section } from "deco/mod.ts"; -import { __DECO_FBT } from "../website/handlers/fresh.ts"; +export const __DECO_FBT = "__decoFBT"; export const shouldForceRender = ( { ctx, searchParams }: { ctx: Ctx; searchParams: URLSearchParams }, ): boolean => ctx.isBot || searchParams.get(__DECO_FBT) === "0"; - -export const renderSection = ({ Component, props }: Section) => ( - -); diff --git a/website/handlers/fresh.ts b/website/handlers/fresh.ts index e6f2f89e0..8be8814cb 100644 --- a/website/handlers/fresh.ts +++ b/website/handlers/fresh.ts @@ -10,10 +10,9 @@ import { DecoState } from "deco/types.ts"; import { allowCorsFor } from "deco/utils/http.ts"; import { getSetCookies } from "std/http/cookie.ts"; import { ConnInfo } from "std/http/server.ts"; +import { __DECO_FBT } from "../../utils/deferred.ts"; import { AppContext } from "../mod.ts"; -export const __DECO_FBT = "__decoFBT"; - /** * @title Fresh Config */ diff --git a/website/manifest.gen.ts b/website/manifest.gen.ts index bc05df6cd..0432f8631 100644 --- a/website/manifest.gen.ts +++ b/website/manifest.gen.ts @@ -48,9 +48,10 @@ import * as $$$$$$$14 from "./matchers/userAgent.ts"; import * as $$$$$0 from "./pages/Page.tsx"; import * as $$$$$$0 from "./sections/Analytics/Analytics.tsx"; import * as $$$$$$1 from "./sections/Rendering/Deferred.tsx"; -import * as $$$$$$2 from "./sections/Rendering/SingleDeferred.tsx"; -import * as $$$$$$3 from "./sections/Seo/Seo.tsx"; -import * as $$$$$$4 from "./sections/Seo/SeoV2.tsx"; +import * as $$$$$$2 from "./sections/Rendering/Lazy.tsx"; +import * as $$$$$$3 from "./sections/Rendering/SingleDeferred.tsx"; +import * as $$$$$$4 from "./sections/Seo/Seo.tsx"; +import * as $$$$$$5 from "./sections/Seo/SeoV2.tsx"; const manifest = { "functions": { @@ -84,9 +85,10 @@ const manifest = { "sections": { "website/sections/Analytics/Analytics.tsx": $$$$$$0, "website/sections/Rendering/Deferred.tsx": $$$$$$1, - "website/sections/Rendering/SingleDeferred.tsx": $$$$$$2, - "website/sections/Seo/Seo.tsx": $$$$$$3, - "website/sections/Seo/SeoV2.tsx": $$$$$$4, + "website/sections/Rendering/Lazy.tsx": $$$$$$2, + "website/sections/Rendering/SingleDeferred.tsx": $$$$$$3, + "website/sections/Seo/Seo.tsx": $$$$$$4, + "website/sections/Seo/SeoV2.tsx": $$$$$$5, }, "matchers": { "website/matchers/always.ts": $$$$$$$0, diff --git a/website/mod.ts b/website/mod.ts index 96e344d14..daec8b57c 100644 --- a/website/mod.ts +++ b/website/mod.ts @@ -104,8 +104,9 @@ export interface Props { caching?: Caching; /** - * @title Async Rendering - * @description Async sections will be deferred to the client-side + * @title Global Async Rendering (Deprecated) + * @description Please disable this setting and enable each section individually. More info at https://deco.cx/en/blog/async-render-default + * @deprecated true * @default false */ firstByteThresholdMS?: boolean; diff --git a/website/sections/Rendering/Deferred.tsx b/website/sections/Rendering/Deferred.tsx index 71e4a8b67..fb55b2d9f 100644 --- a/website/sections/Rendering/Deferred.tsx +++ b/website/sections/Rendering/Deferred.tsx @@ -4,7 +4,7 @@ import { useScriptAsDataURI } from "deco/hooks/useScript.ts"; import { asResolved, isDeferred } from "deco/mod.ts"; import { useId } from "preact/hooks"; import { AppContext } from "../../mod.ts"; -import { renderSection, shouldForceRender } from "../../../utils/deferred.tsx"; +import { shouldForceRender } from "../../../utils/deferred.ts"; /** @titleBy type */ export interface Scroll { @@ -43,8 +43,6 @@ export interface Props { sections: Section[]; display?: boolean; behavior?: Scroll | Intersection | Load; - /** @hide true */ - fallbacks?: Section[]; } const script = ( @@ -103,7 +101,7 @@ const Deferred = (props: Props) => { if (display) { return ( <> - {sections.map(renderSection)} + {sections.map(({ Component, props }) => )} ); } @@ -125,7 +123,6 @@ const Deferred = (props: Props) => { behavior?.payload.toString() || "", )} /> - {props.fallbacks?.map(renderSection)} ); }; diff --git a/website/sections/Rendering/Lazy.tsx b/website/sections/Rendering/Lazy.tsx new file mode 100644 index 000000000..b2d35559b --- /dev/null +++ b/website/sections/Rendering/Lazy.tsx @@ -0,0 +1,145 @@ +import type { Section } from "deco/blocks/section.ts"; +import { SectionContext } from "deco/components/section.tsx"; +import { asResolved, context } from "deco/mod.ts"; +import { useContext } from "preact/hooks"; +import { shouldForceRender } from "../../../utils/deferred.ts"; +import type { AppContext } from "../../mod.ts"; + +const useSectionContext = () => useContext(SectionContext); + +interface Props { + /** @label hidden */ + section: Section; + + /** + * @description htmx/Deferred.tsx prop + * @hide true + */ + loading?: "eager" | "lazy"; +} + +const defaultFallbackFor = (section: string) => () => ( +
+ {!context.isDeploy && ( + <> +
+ Async Rendering not implemented for section{" "} + {section} +
+
+ If you are a developer, export a{" "} + LoadingFallback{" "} + component in this section. To learn more, check out our{" "} + + guide + +
+
+ If you are NOT a developer, you can tweak Async Rendering. To learn + more, check out our{" "} + + blog post + +
+ + )} +
+); + +export const loader = async (props: Props, req: Request, ctx: AppContext) => { + const { section, loading } = props; + const url = new URL(req.url); + + const shouldRender = loading === "eager" || shouldForceRender({ + ctx, + searchParams: url.searchParams, + }); + + if (shouldRender) { + return { + loading: "eager", + section: await ctx.get
(section), + }; + } + + const resolvingMatchers: Record = {}; + const resolvedSection = await ctx.get
(section, { + propagateOptions: true, + hooks: { + onPropsResolveStart: ( + resolve, + _props, + resolver, + _resolveType, + ctx, + ) => { + if (resolvingMatchers[ctx.resolveId]) { + return resolve(); + } + if (resolver?.type === "matchers") { // matchers should not have a timeout. + const id = crypto.randomUUID(); + resolvingMatchers[id] = true; + return resolve(id); + } + if (resolver?.type === "loaders") { + // deno-lint-ignore no-explicit-any + return undefined as any; + } + return resolve(); + }, + }, + }); + + return { + loading: shouldRender ? "eager" : "lazy", + section: { + Component: resolvedSection.LoadingFallback ?? + defaultFallbackFor(resolvedSection.metadata?.component ?? "unknown"), + props: {}, + }, + }; +}; + +type SectionProps = Awaited>; + +function Lazy({ section, loading }: SectionProps) { + const ctx = useSectionContext(); + + if (!ctx) { + throw new Error("Missing SectionContext"); + } + + if (loading === "lazy") { + return ( + + + + ); + } + + return ; +} + +export const onBeforeResolveProps = (props: Props) => ({ + ...props, + section: asResolved(props.section), +}); + +export default Lazy; diff --git a/website/sections/Rendering/SingleDeferred.tsx b/website/sections/Rendering/SingleDeferred.tsx index 399e574af..94dc9152f 100644 --- a/website/sections/Rendering/SingleDeferred.tsx +++ b/website/sections/Rendering/SingleDeferred.tsx @@ -1,107 +1,2 @@ -import type { Section } from "deco/blocks/section.ts"; -import { SectionContext } from "deco/components/section.tsx"; -import { RequestContext } from "deco/deco.ts"; -import { asResolved, isDeferred } from "deco/mod.ts"; -import { useContext } from "preact/hooks"; -import HTMXDeferred from "../../../htmx/sections/Deferred.tsx"; -import { shouldForceRender } from "../../../utils/deferred.tsx"; -import type { AppContext } from "../../mod.ts"; -import PartialDeferred from "./Deferred.tsx"; - -const isHtmx = ( - props: SectionProps, -): props is SectionProps & { framework: "htmx" } => props.framework === "htmx"; - -interface Props { - /** @label hidden */ - section: Section; - /** - * @description fresh/Deferred.tsx props - * @hide true - */ - display?: boolean; - /** - * @description htmx/Deferred.tsx prop - * @hide true - */ - loading?: "eager"; -} - -export const loader = async ( - props: Props, - _req: Request, - ctx: AppContext, -) => { - const isFreshSyncRender = "display" in props && props.display === true; - const isHtmxSyncRender = "loading" in props && props.loading === "eager"; - const url = new URL(_req.url); - const _shouldForceRender = shouldForceRender({ - ctx, - searchParams: url.searchParams, - }); - const shouldRender = isFreshSyncRender || isHtmxSyncRender || - _shouldForceRender; - const framework = ctx.flavor?.framework || "fresh"; - - if (shouldRender) { - const section = isDeferred
(props.section) - ? await props.section() - : props.section; - return { ...props, framework, section, fallback: null }; - } - - // How to improve it - const abortControler = new AbortController(); - abortControler.abort(); - const section = isDeferred
(props.section) - ? await RequestContext.bind( - { signal: abortControler.signal }, - props.section, - )() - : props.section; - - return { ...props, framework, section: null, fallback: section }; -}; - -type SectionProps = Awaited>; - -function SingleDeferred(props: SectionProps) { - const ctx = useContext(SectionContext)!; - const idxOrNaN = Number(ctx?.resolveChain.at(-2)?.value); - const delay = 25 * (Math.min(Number.isNaN(idxOrNaN) ? 1 : idxOrNaN, 10) || 1); - const sections = props.section ? [props.section] : []; - const fallbacks = props.fallback ? [props.fallback] : undefined; - - return ( - - {isHtmx(props) - ? ( - - ) - : ( - - )} - - ); -} - -export const onBeforeResolveProps = (props: Props) => { - return { - ...props, - section: asResolved(props.section, true), - }; -}; - -export default SingleDeferred; +export * from "./Lazy.tsx"; +export { default } from "./Lazy.tsx"; From b0b7ce46284747aa923b957416377245080c7523 Mon Sep 17 00:00:00 2001 From: gimenes Date: Wed, 24 Jul 2024 16:53:05 -0300 Subject: [PATCH 2/9] async rendering --- website/sections/Rendering/Lazy.tsx | 57 +++++++++++++++-------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/website/sections/Rendering/Lazy.tsx b/website/sections/Rendering/Lazy.tsx index b2d35559b..151aa2fab 100644 --- a/website/sections/Rendering/Lazy.tsx +++ b/website/sections/Rendering/Lazy.tsx @@ -1,6 +1,6 @@ import type { Section } from "deco/blocks/section.ts"; import { SectionContext } from "deco/components/section.tsx"; -import { asResolved, context } from "deco/mod.ts"; +import { asResolved, context, isDeferred } from "deco/mod.ts"; import { useContext } from "preact/hooks"; import { shouldForceRender } from "../../../utils/deferred.ts"; import type { AppContext } from "../../mod.ts"; @@ -75,43 +75,46 @@ export const loader = async (props: Props, req: Request, ctx: AppContext) => { if (shouldRender) { return { loading: "eager", - section: await ctx.get
(section), + section: isDeferred
(section) ? await section() : section, }; } const resolvingMatchers: Record = {}; - const resolvedSection = await ctx.get
(section, { - propagateOptions: true, - hooks: { - onPropsResolveStart: ( - resolve, - _props, - resolver, - _resolveType, - ctx, - ) => { - if (resolvingMatchers[ctx.resolveId]) { + const resolvedSection = isDeferred
(section) + ? await section({}, { + propagateOptions: true, + hooks: { + onPropsResolveStart: ( + resolve, + _props, + resolver, + _resolveType, + ctx, + ) => { + if (resolvingMatchers[ctx.resolveId]) { + return resolve(); + } + if (resolver?.type === "matchers") { // matchers should not have a timeout. + const id = crypto.randomUUID(); + resolvingMatchers[id] = true; + return resolve(id); + } + if (resolver?.type === "loaders") { + // deno-lint-ignore no-explicit-any + return undefined as any; + } return resolve(); - } - if (resolver?.type === "matchers") { // matchers should not have a timeout. - const id = crypto.randomUUID(); - resolvingMatchers[id] = true; - return resolve(id); - } - if (resolver?.type === "loaders") { - // deno-lint-ignore no-explicit-any - return undefined as any; - } - return resolve(); + }, }, - }, - }); + }) + : section; return { loading: shouldRender ? "eager" : "lazy", section: { Component: resolvedSection.LoadingFallback ?? defaultFallbackFor(resolvedSection.metadata?.component ?? "unknown"), + metadata: resolvedSection.metadata, props: {}, }, }; @@ -139,7 +142,7 @@ function Lazy({ section, loading }: SectionProps) { export const onBeforeResolveProps = (props: Props) => ({ ...props, - section: asResolved(props.section), + section: asResolved(props.section, true), }); export default Lazy; From 222f20ad087994ae92a7f0871b5edc4a2e26c1dc Mon Sep 17 00:00:00 2001 From: Marcos Candeia Date: Wed, 24 Jul 2024 16:59:25 -0300 Subject: [PATCH 3/9] Fix loading loaders on resolveStart Signed-off-by: Marcos Candeia --- website/sections/Rendering/Lazy.tsx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/website/sections/Rendering/Lazy.tsx b/website/sections/Rendering/Lazy.tsx index 151aa2fab..a0688ad3f 100644 --- a/website/sections/Rendering/Lazy.tsx +++ b/website/sections/Rendering/Lazy.tsx @@ -84,6 +84,16 @@ export const loader = async (props: Props, req: Request, ctx: AppContext) => { ? await section({}, { propagateOptions: true, hooks: { + onResolveStart: (resolve, _props, resolver, _resolveType, ctx) => { + if (resolvingMatchers[ctx.resolveId]) { + return resolve(); + } + if (resolver.type === "loaders") { + // deno-lint-ignore no-explicit-any + return undefined as any; + } + return resolve(); + }, onPropsResolveStart: ( resolve, _props, @@ -99,10 +109,6 @@ export const loader = async (props: Props, req: Request, ctx: AppContext) => { resolvingMatchers[id] = true; return resolve(id); } - if (resolver?.type === "loaders") { - // deno-lint-ignore no-explicit-any - return undefined as any; - } return resolve(); }, }, From 891b78102569a6eb6ebaf1b51989239cbf3eb815 Mon Sep 17 00:00:00 2001 From: Marcos Candeia Date: Thu, 25 Jul 2024 10:35:26 -0300 Subject: [PATCH 4/9] Do not resolve loaders props Signed-off-by: Marcos Candeia --- website/sections/Rendering/Lazy.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/website/sections/Rendering/Lazy.tsx b/website/sections/Rendering/Lazy.tsx index a0688ad3f..fcdd59908 100644 --- a/website/sections/Rendering/Lazy.tsx +++ b/website/sections/Rendering/Lazy.tsx @@ -109,6 +109,10 @@ export const loader = async (props: Props, req: Request, ctx: AppContext) => { resolvingMatchers[id] = true; return resolve(id); } + if (resolver.type === "loaders") { + // deno-lint-ignore no-explicit-any + return undefined as any; + } return resolve(); }, }, From 2eb1f578dee99a5af73e051699dbaf1b7de6c919 Mon Sep 17 00:00:00 2001 From: Marcos Candeia Date: Thu, 25 Jul 2024 10:38:17 -0300 Subject: [PATCH 5/9] Fix nul check Signed-off-by: Marcos Candeia --- website/sections/Rendering/Lazy.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/sections/Rendering/Lazy.tsx b/website/sections/Rendering/Lazy.tsx index fcdd59908..8c5932a9f 100644 --- a/website/sections/Rendering/Lazy.tsx +++ b/website/sections/Rendering/Lazy.tsx @@ -109,7 +109,7 @@ export const loader = async (props: Props, req: Request, ctx: AppContext) => { resolvingMatchers[id] = true; return resolve(id); } - if (resolver.type === "loaders") { + if (resolver?.type === "loaders") { // deno-lint-ignore no-explicit-any return undefined as any; } From 2bd9646a84c641ef9629192e76372ef1bb47a03e Mon Sep 17 00:00:00 2001 From: Marcos Candeia Date: Thu, 25 Jul 2024 10:50:50 -0300 Subject: [PATCH 6/9] Do not invoke loaders Signed-off-by: Marcos Candeia --- website/sections/Rendering/Lazy.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/sections/Rendering/Lazy.tsx b/website/sections/Rendering/Lazy.tsx index 8c5932a9f..f50fff5d7 100644 --- a/website/sections/Rendering/Lazy.tsx +++ b/website/sections/Rendering/Lazy.tsx @@ -85,10 +85,10 @@ export const loader = async (props: Props, req: Request, ctx: AppContext) => { propagateOptions: true, hooks: { onResolveStart: (resolve, _props, resolver, _resolveType, ctx) => { - if (resolvingMatchers[ctx.resolveId]) { + if (ctx.resolveId in resolvingMatchers) { return resolve(); } - if (resolver.type === "loaders") { + if (resolver?.type === "loaders") { // deno-lint-ignore no-explicit-any return undefined as any; } @@ -101,7 +101,7 @@ export const loader = async (props: Props, req: Request, ctx: AppContext) => { _resolveType, ctx, ) => { - if (resolvingMatchers[ctx.resolveId]) { + if (ctx.resolveId in resolvingMatchers) { return resolve(); } if (resolver?.type === "matchers") { // matchers should not have a timeout. From 9e380758530e02d4686579f3e957d50315cbd54c Mon Sep 17 00:00:00 2001 From: Marcos Candeia Date: Thu, 25 Jul 2024 10:53:55 -0300 Subject: [PATCH 7/9] Resolve empty props Signed-off-by: Marcos Candeia --- website/sections/Rendering/Lazy.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/website/sections/Rendering/Lazy.tsx b/website/sections/Rendering/Lazy.tsx index f50fff5d7..be8d7047b 100644 --- a/website/sections/Rendering/Lazy.tsx +++ b/website/sections/Rendering/Lazy.tsx @@ -110,8 +110,7 @@ export const loader = async (props: Props, req: Request, ctx: AppContext) => { return resolve(id); } if (resolver?.type === "loaders") { - // deno-lint-ignore no-explicit-any - return undefined as any; + return Promise.resolve([]); } return resolve(); }, From e24dfd528bd7e6219dfe7747701121f6187150e7 Mon Sep 17 00:00:00 2001 From: Marcos Candeia Date: Thu, 25 Jul 2024 11:02:17 -0300 Subject: [PATCH 8/9] Rollback deferred to old version Signed-off-by: Marcos Candeia --- deno.json | 2 +- htmx/sections/Deferred.tsx | 31 ++++++++++++++++--------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/deno.json b/deno.json index 7977979b2..236436979 100644 --- a/deno.json +++ b/deno.json @@ -9,7 +9,7 @@ "std/": "https://deno.land/std@0.204.0/", "partytown/": "https://deno.land/x/partytown@0.4.8/", "deco-sites/std/": "https://denopkg.com/deco-sites/std@1.26.7/", - "deco/": "https://cdn.jsdelivr.net/gh/deco-cx/deco@30aa5339af59f53d5452b29eebde196a1df66a16/" + "deco/": "https://cdn.jsdelivr.net/gh/deco-cx/deco@1.80.0/" }, "lock": false, "tasks": { diff --git a/htmx/sections/Deferred.tsx b/htmx/sections/Deferred.tsx index 0c3401765..9014fd6cb 100644 --- a/htmx/sections/Deferred.tsx +++ b/htmx/sections/Deferred.tsx @@ -1,8 +1,8 @@ import type { Section } from "deco/blocks/section.ts"; import { useSection } from "deco/hooks/useSection.ts"; import { asResolved, isDeferred } from "deco/mod.ts"; +import { renderSection, shouldForceRender } from "../../utils/deferred.tsx"; import { AppContext } from "../mod.ts"; -import { shouldForceRender } from "../../utils/deferred.ts"; /** * @titleBy type @@ -10,8 +10,7 @@ import { shouldForceRender } from "../../utils/deferred.ts"; */ interface Load { type: "load"; - - // TODO: @gimenes add delay + /** @hide true */ delay?: number; } @@ -35,18 +34,19 @@ interface Intersect { export interface Props { sections: Section[]; - fallback?: Section; + /** @hide true */ + fallbacks?: Section[]; trigger?: Load | Revealed | Intersect; loading?: "lazy" | "eager"; } const Deferred = (props: Props) => { - const { sections, loading, trigger, fallback } = props; + const { sections, loading, trigger } = props; if (loading === "eager") { return ( <> - {sections.map(({ Component, props }) => )} + {sections.map(renderSection)} ); } @@ -61,15 +61,16 @@ const Deferred = (props: Props) => { } return ( -
- {fallback && } -
+ <> +
+ {props.fallbacks?.map(renderSection)} + ); }; From 7663c2f8e31d09a991c6d1215843751dacc73434 Mon Sep 17 00:00:00 2001 From: Marcos Candeia Date: Thu, 25 Jul 2024 11:05:16 -0300 Subject: [PATCH 9/9] Fix deferred checks Signed-off-by: Marcos Candeia --- htmx/sections/Deferred.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/htmx/sections/Deferred.tsx b/htmx/sections/Deferred.tsx index 9014fd6cb..1ff504fbb 100644 --- a/htmx/sections/Deferred.tsx +++ b/htmx/sections/Deferred.tsx @@ -1,7 +1,7 @@ import type { Section } from "deco/blocks/section.ts"; import { useSection } from "deco/hooks/useSection.ts"; import { asResolved, isDeferred } from "deco/mod.ts"; -import { renderSection, shouldForceRender } from "../../utils/deferred.tsx"; +import { shouldForceRender } from "../../utils/deferred.ts"; import { AppContext } from "../mod.ts"; /** @@ -46,7 +46,7 @@ const Deferred = (props: Props) => { if (loading === "eager") { return ( <> - {sections.map(renderSection)} + {sections.map((section) => )} ); } @@ -69,7 +69,9 @@ const Deferred = (props: Props) => { hx-swap="outerHTML" style={{ height: "100vh" }} /> - {props.fallbacks?.map(renderSection)} + {props.fallbacks?.map((section) => + section ? : null + )} ); };