How dynamically render page layouts from the CMS?
Answered
Sun bear posted this in #help-forum
Sun bearOP
I am creating a "website builder" of sorts. I have created common website sections as react components, which take their content as props. (Image #1)
These sections have schemas matching them in my CMS. This allows the user to simply click "Add Section" in CMS, add sections and their respective content and basically build an entire webpage structure inside the CMS. (Image #2)
Since the user can create multiple pages, for example
But the problem arises when the dynamically rendering the page layout from the schema example in the (Image #2). I was thinking of creating a [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) and storing the
The comment above explains the issue. I cannot really pass the
I have 2 questions I want to ask here.
1. Is Next.js and Sanity.io a good stack for something like this or are there any alternatives making such configuration easier to implement?
2. How can I pass the
These sections have schemas matching them in my CMS. This allows the user to simply click "Add Section" in CMS, add sections and their respective content and basically build an entire webpage structure inside the CMS. (Image #2)
Since the user can create multiple pages, for example
/about, /pricing, etc. I will be dynamically rendering these routes by fetching the object with the matching route matcher in my CMS database.But the problem arises when the dynamically rendering the page layout from the schema example in the (Image #2). I was thinking of creating a [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) and storing the
ComponentName as key and the ComponentObject as value, then mapping over the fetched layout like the example below:import sectionsMap from "data/sections-map.ts"
export async function DynamicPage({pagePath}: {pagePath: string}) {
// LayoutType refers to the type similar to the one shown in (Image #2)
const layout = await getPageLayout(pagePath)
// Notice how with this I cannot pass the Fields into my component
return (
<main>
{
layout.map((layoutSection) => sectionsMap.get(layoutSection.Section))
}
</main>
)
}The comment above explains the issue. I cannot really pass the
Fields object as props to my component.I have 2 questions I want to ask here.
1. Is Next.js and Sanity.io a good stack for something like this or are there any alternatives making such configuration easier to implement?
2. How can I pass the
Fields as props to my component gotten from the sectionsMap?Answered by B33fb0n3
The mapping itself would work like „data.map((oneItem) => { … }“ and inside it you can render a „Section“ component for example. Inside this „Section“ component you create a switch, that switches the type of the current section. Like that you can spread the data to the specific components and render only what you need. You should render the switch serverside to keep everything as small as possible
14 Replies
Is Next.js and Sanity.io a good stack for something like this or are there any alternatives making such configuration easier to implement?I dont nearly excatly that and I am fine with nextjs and a database setup
How can I pass the Fields as props to my component gotten from the sectionsMap?You can just pass them down as regular props. It's just data 🙂
@B33fb0n3 > Is Next.js and Sanity.io a good stack for something like this or are there any alternatives making such configuration easier to implement?
I dont nearly excatly that and I am fine with nextjs and a database setup
> How can I pass the Fields as props to my component gotten from the sectionsMap?
You can just pass them down as regular props. It's just data 🙂
Sun bearOP
Can you show me the code code example for 2.
@Sun bear Can you show me the code code example for 2.
yea:
<ImageWithContent data={data.fields}/>
// or spread
<ImageWithContent {...data.fields}/>
// same for CallToAction
<CallToAction data={data.fields}/>
// or spread
<CallToAction {...data.fields}/>Sun bearOP
I didn't mean it like that. I get an array of sections from my database. Now I have to dynamically render these based on an array that looks something like this:
So this should end up being rendered as:
const layout = [
{
section: "image-with-content",
fields: {
imageUrl: "www.image-provider.com/image-id/123",
title: "Hello World!",
content: "Lorem ispum dolor sit."
}
},
{
section: "call-to-action",
fields: {
title: "Hello World!",
content: "Lorem ispum dolor sit.",
button: {
text: "Get started",
href: "/get-started"
}
}
}
]So this should end up being rendered as:
return (
<ImageWithContent {...layout[0].fields} />
<CallToAction {...layout[1].fields} />
)I know how to spread the fields into a component as props, but I don't know how to do that when selecting components based on a map that returns them.
I've been thinking of creating a helper component called
<DynamicComponent /> that has a switch return statement that returns the components depending on section string gotten from the databaseBut this would require me to have an abnormally large component that has has many unnecessary imports.
@Sun bear I know how to spread the fields into a component as props, but I don't know how to do that when selecting components based on a map that returns them.
The mapping itself would work like „data.map((oneItem) => { … }“ and inside it you can render a „Section“ component for example. Inside this „Section“ component you create a switch, that switches the type of the current section. Like that you can spread the data to the specific components and render only what you need. You should render the switch serverside to keep everything as small as possible
Answer
Sun bearOP
thanks
would making the components a dynamic import fix the bundle size?
@Sun bear would making the components a dynamic import fix the bundle size?
SSR is a good approach to render stuff fast
@Sun bear solved?
Sun bearOP
yes thank you