·8 min read
React Component for YouTube Channel Banners Using banner.yt
Build a reusable React component that displays a YouTube channel banner, avatar, and stats by fetching from the banner.yt API.
ReactComponentAPITutorialJavaScript
YouTube Channel Banner Component in React
Here is a reusable React component that loads a channel banner, avatar, name, and subscriber count from the banner.yt API.
ChannelCard.tsx
import { useEffect, useState } from 'react';
interface ChannelData {
channelId: string;
title: string;
description: string;
subscriberCount: string;
viewCount: string;
bannerUrl: string;
avatarUrl: string;
}
interface Props {
channelId: string;
}
export default function ChannelCard({ channelId }: Props) {
const [channel, setChannel] = useState<ChannelData | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(`https://banner.yt/api/channel/${channelId}`)
.then(r => r.json())
.then(data => {
setChannel(data);
setLoading(false);
})
.catch(() => setLoading(false));
}, [channelId]);
if (loading) return <div className="channel-card loading">Loading...</div>;
if (!channel) return <div className="channel-card error">Channel not found</div>;
const bannerSrc = `https://banner.yt/api/banner/${channelId}?format=webp`;
const avatarSrc = `https://banner.yt/api/banner/${channelId}?type=avatar&format=webp`;
const formatSubs = (n: string) => {
const num = parseInt(n, 10);
if (num >= 1e9) return (num / 1e9).toFixed(1) + 'B';
if (num >= 1e6) return (num / 1e6).toFixed(1) + 'M';
if (num >= 1e3) return (num / 1e3).toFixed(1) + 'K';
return n;
};
return (
<div style={{
borderRadius: 12,
overflow: 'hidden',
border: '1px solid #333',
background: '#111',
maxWidth: 560,
}}>
<img
src={bannerSrc}
alt={`${channel.title} YouTube banner`}
style={{ width: '100%', display: 'block' }}
loading="lazy"
/>
<div style={{ display: 'flex', alignItems: 'center', gap: 12, padding: 12 }}>
<img
src={avatarSrc}
alt={channel.title}
width={48}
height={48}
style={{ borderRadius: '50%' }}
/>
<div>
<div style={{ fontWeight: 'bold', color: '#fff' }}>{channel.title}</div>
<div style={{ fontSize: 13, color: '#aaa' }}>
{formatSubs(channel.subscriberCount)} subscribers
</div>
</div>
</div>
</div>
);
}
Usage
import ChannelCard from './ChannelCard';
export default function App() {
return (
<div>
<h1>Top Channels</h1>
<ChannelCard channelId="UCX6OQ3DkcsbYNE6H8uQQuVA" />
<ChannelCard channelId="UC-lHJZR3Gqxm24_Vd_AJ5Yw" />
</div>
);
}
Next.js with server components
In Next.js 13+ you can fetch on the server and avoid the loading state entirely:
// app/channel/[id]/page.tsx
async function getChannel(id: string) {
const res = await fetch(`https://banner.yt/api/channel/${id}`, {
next: { revalidate: 3600 } // cache for 1 hour
});
return res.json();
}
export default async function ChannelPage({ params }: { params: { id: string } }) {
const channel = await getChannel(params.id);
return (
<main>
<img
src={`https://banner.yt/api/banner/${params.id}`}
alt={`${channel.title} banner`}
style={{ width: '100%' }}
/>
<h1>{channel.title}</h1>
<p>{channel.subscriberCount} subscribers</p>
</main>
);
}