#How can I dynamically display components

1 messages ยท Page 1 of 1 (latest)

scenic flume
#

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)

#

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 ๐Ÿ˜‰