Last active
September 7, 2021 11:38
-
-
Save jferrettiboke/b01ed07c9953f8f4ab9917f4f9a4ebe7 to your computer and use it in GitHub Desktop.
Map CMS modules to React.js components idea
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// CMS | |
const pages = [ | |
{ | |
id: "1", | |
slug: "/", | |
modules: [ | |
{ type: "hero", title: "Hero title", description: "Hero description" }, | |
{ type: "image", title: "Image title", url: "https://..." }, | |
], | |
}, | |
]; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// components/builder.jsx | |
import moduleList from "@/components/modules"; | |
export default function Builder({ components }) { | |
return ( | |
<> | |
{components.map((component, i) => { | |
if (!component) { | |
return null; | |
} | |
const { name, props } = component; | |
const Component = moduleList[name] || null; | |
if (Component) { | |
return <Component key={`${i}-component-${name}`} {...props} />; | |
} | |
return ( | |
<div key={`${i}-component-${name}`} {...props}> | |
<p>{name} cannot be resolved</p> | |
</div> | |
); | |
})} | |
</> | |
); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// components/hero.jsx | |
export default function Hero({ title, description }) { | |
return ( | |
<div className="hero"> | |
<div className="hero-title">{title}<div> | |
<div className="hero-description">{description}<div> | |
</div> | |
); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// components/image.jsx | |
export default function Image({ title, src }) { | |
return <img src={src} alt={title} /> | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// components/modules.js | |
import dynamic from "next/dynamic"; | |
const modules = { | |
HeroComponent: dynamic(() => import("./hero")), | |
ImageComponent: dynamic(() => import("./image")), | |
}; | |
export default modules; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// pages/[[...slug]].jsx | |
import Head from "next/head"; | |
import Builder from "@/components/builder"; | |
export default function Page({ page }) { | |
return ( | |
<> | |
<Head> | |
<title>{page.title}</title> | |
</Head> | |
<Builder components={page.components} /> | |
</> | |
); | |
} | |
export async function getStaticProps({ locale, params: { slug } }) { | |
const currentPage = await getPage({ | |
slug: slug ? `/${slug.join("/")}` : "/", | |
locale, | |
}); | |
const page = getPageProps({ page: currentPage, locale }); | |
return { | |
props: { | |
page, | |
}, | |
notFound: !!!page, | |
}; | |
} | |
function getPageProps({ page, locale }) { | |
return { | |
slug: page.slug[locale], | |
title: page.title[locale], | |
components: page.modules.map((pageModule) => mapModuleToProps(pageModule)), | |
}; | |
} | |
function mapModuleToProps({ type, ...pageModule }) { | |
switch (type) { | |
case "hero": | |
return { | |
name: "HeroComponent", | |
props: { | |
title: pageModule.title ?? null, | |
description: pageModule.description ?? null, | |
}, | |
}; | |
case "image": | |
return { | |
name: "ImageComponent", | |
props: { | |
title: pageModule.title ?? null, | |
src: pageModule.url ?? null, | |
}, | |
}; | |
default: | |
return undefined; | |
} | |
} |
That's correct.
I have updated the Gist. Have a look at components-modules.js
and components-builder.jsx
again.
Let me know whatever!
Thanks, all clear.
My second question goes why the JSX inside builder.jsx
return function starts in curly brackets {}
?
// components/builder.jsx
export default function Builder({ components }) {
return (
<>
{ /* code here */ }
</>
);
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for pasting this gist, it helps a lot.
I am trying to understand what does
getComponent()
function inbuilder.jsx
do? Is this just returning a dynamic component?