#How can I dynamically display components
1 messages ยท Page 1 of 1 (latest)
This is how I do in my app:
async function getFeed() {
return [
{ type: "news", title: "Hello world", content: "๐" },
{
type: "system",
content:
"We're going to be down for maintenance on Friday @ 2pm EST. Please save your work and log out before then.",
} as const,
];
}
type Feed = Awaited<ReturnType<typeof getFeed>>;
export default async function Page() {
return (
<div>
<h1>Switch</h1>
<Feed />
</div>
);
}
async function Feed() {
const feed = await getFeed();
return (
<div>
{feed.map((item) => {
switch (item.type) {
case "news":
return <NewsItem item={item} />;
case "system":
return <SystemItem item={item} />;
}
})}
</div>
);
}
function NewsItem({ item }: { item: { title: string; content: string } }) {
return (
<div>
<h2>{item.title}</h2>
<p>{item.content}</p>
</div>
);
}
function SystemItem({ item }: { item: { content: string } }) {
return <div>{item.content}</div>;
}
I have inlined this example but it works with importing components too
The key part is to have a discriminant on the API response (string literal or enum)
this is an 'old' way of using JS but much easier to debug/maintain ๐ .
You can also look at ts-pattern https://github.com/gvergnaud/ts-pattern
If for any reason you want to lazy load these components (maybe they have to fetch something else on their side),:
import { Suspense, lazy } from "react";
const NewsItem = lazy(() => import("./components/news"));
const SystemItem = lazy(() => import("./components/system"));
async function getFeed() {
return [
{ type: "news", title: "Hello world", content: "๐" },
{
type: "system",
content:
"We're going to be down for maintenance on Friday @ 2pm EST. Please save your work and log out before then.",
} as const,
];
}
type Feed = Awaited<ReturnType<typeof getFeed>>;
export async function Feed() {
const feed = await getFeed();
return (
<div>
{feed.map((item) => {
switch (item.type) {
case "news":
return (
<Suspense fallback={<div>Loading...</div>}>
<NewsItem item={item} />
</Suspense>
);
case "system":
return (
<Suspense fallback={<div>Loading...</div>}>
<SystemItem item={item} />
</Suspense>
);
}
})}
</div>
);
}
These coomponents has to be default exported ๐