2.9 KiB
blocks
RenderBlocks — generyczny, serwerowy silnik renderowania bloków. Plugin nie
zna Twoich bloków: iteruje po danych, mapuje blockType → komponent przez
registry (prop), obsługuje zagnieżdżanie i rozszerzenia per-blok. Bloki
(schemat + komponenty) definiujesz u siebie.
Config
Brak opcji w payload.config — bloki definiujesz w swoich kolekcjach
(pole typu blocks). Plugin dostarcza tylko silnik renderujący.
⚠️ NIE pisz własnego renderera bloków (switch)
Renderer bloków to RenderBlocks z pluginu — NIGDY własny switch/if.
Częsty błąd: projekt pisze własny BlockRenderer z switch (block.blockType)
i 20 case'ami. To łamie A0 — plugin ma silnik, projekt dostarcza tylko MAPĘ
komponentów.
// ŹLE — własny switch w projekcie (gadatliwy, bez enhanceProps, rośnie liniowo)
switch (block.blockType) {
case 'hero': return <Hero {...block} />
case 'faq': return <FAQ {...block} />
// ...20 case'ów
}
// DOBRZE — mapa + RenderBlocks (silnik z pluginu)
const registry = { hero: Hero, faq: FAQ, /* ... */ }
<RenderBlocks blocks={page.layout} components={registry} />
Dlaczego RenderBlocks, nie switch: enhanceProps (anchory nav, itp.), guardy, obsługa zagnieżdżeń, spójność między projektami. Switch tego nie ma i rośnie z każdym blokiem. Mapa jest płaska i deklaratywna.
Front — RenderBlocks
Import z @intecion/ipal-kit/rsc (to komponent serwerowy):
import { RenderBlocks } from '@intecion/ipal-kit/rsc'
// Twój registry: blockType → komponent (komponenty są Twoje)
import { Hero } from '@/blocks/Hero'
import { FormBlock } from '@/blocks/FormBlock'
const registry = { hero: Hero, formBlock: FormBlock }
export default async function Page() {
const page = await payload.findByID({ collection: 'pages', id })
return <RenderBlocks blocks={page.layout} components={registry} />
}
- nieznany
blockType→ pomijany (null), nie crashuje - każdy blok dostaje
_components(mapę) — do rekursji zagnieżdżonych bloków bez React Context (wymóg RSC)
enhanceProps — logika per-blok bez wiedzy pluginu
Gdy blok potrzebuje danych z innych bloków (np. nawigacja zbierająca kotwice
z sekcji), podaj enhanceProps. Plugin go wywołuje, nie znając Twoich bloków:
const enhanceProps = ({ block, allBlocks }) => {
if (block.blockType !== 'sectionNav') return {}
const sections = allBlocks
.filter((b) => b.blockType === 'anchoredSection')
.map((b) => ({ anchor: b.anchor, label: b.navLabel }))
return { _sections: sections }
}
<RenderBlocks blocks={page.layout} components={registry} enhanceProps={enhanceProps} />
Komponent bloku
Każdy komponent dostaje dane bloku jako propsy (plus _components, plus to co
zwróci enhanceProps). Spacing/layout należą do Ciebie — silnik nie owija
bloków żadnym markupem.
export function Hero(props) {
return <section className="py-16">{/* ... */}</section>
}