In the last two sections, we built the static sections of the YouTube clone. In this section, we will fetch the data for the content of the webpage. So, to do that, let's create the following serverSideProp in the index.js file:
export async function getServerSideProps(context){
const query = context.query.query;
const header = {
'X-RapidAPI-Key': process.env.NEXT_APP_API_KEY,
'X-RapidAPI-Host': RapidAPI-Host
}
{/* If the user submitted something from the input field, then fetch for that keyword else fetch for trending videos */}
if (query){
const options = {
method: 'GET',
url: 'https://youtube-search-and-download.p.rapidapi.com/search',
params: {
query: query,
hl: 'en',
type: 'v'
},
headers:header
};
const response = await axios.request(options);
return {
props: {
data: response.data.contents
}
}
}else{
const options = {
method: 'GET',
url: 'https://youtube-search-and-download.p.rapidapi.com/trending',
params: { hl: 'en'},
headers:header
};
const response = await axios.request(options);
return {
props: {
data: response.data.contents
}
}
}
}
So, now to access the data, all you have to do is:
export default function Home({data}){
}
and Pass the data to the body component:
<Body data={data} />
If you remember correctly, our Body.js file looked something like this:
function Body({data}) {
return (
<div className="col-span-6 relative min-h-screen z-0 ml-4 lg:ml-20">
<VideoPlayer data={data} />
</div>
)
}
Now, the VideoPlayer.js component is the important part:
First, we import all our necessary dependencies, which are:
import {BsDot, BsThreeDots} from 'react-icons/bs'
import ReactPlayer from 'react-player/lazy'
import Skeleton from 'react-loading-skeleton'
import 'react-loading-skeleton/dist/skeleton.css'
Then, we build the component with the data we got from the query:
function VideoPlayer({data}) {
// Set loading feature
const [loading, setloading] = useState(false)
useEffect(() =>{
setTimeout(() => {
setloading(true)
}, 2000)
}, [])
return (
<div className='flex flex-wrap gap-5 items-center justify-center my-10'>
{data && data.map((item, index) => {
return (
<div className='flex flex-col items-center ml-10 md:ml-0' key={index}>
<div className='relative '>
{loading ? (
<>
<ReactPlayer url={`https://www.youtube.com/watch?v=${item? item.video.videoId: 'Ux_LFXpOrd4'}`} light height={220} width={380}/>
<span className='absolute bottom-2 right-3 bg-black text-white p-0.5'>{item.video.lengthText}</span>
</>
) : <Skeleton height={220} width={380} />}
</div>
<div className='flex mt-4 ml-1'>
{/* Note that for better image rendering, you can use the Image component from next/image */}
<img src='/youtube.jpg' alt='channel-logo' className='rounded-full mr-3 w-10 h-10 object-cover'/>
<div>
<div className='flex justify-between w-80 mb-1'>
<div><h2 className='text-xl font-bold'>{item? item.video.title.length > 45? `${item.video.title.slice(0,45)}...`:item.video.title:<Skeleton />}</h2></div>
<div className='rounded-full h-10 w-10 text-center flex items-center justify-center transition-all hover:bg-gray-100'><BsThreeDots size={20} className='rotate-90'/></div>
</div>
<div className='opacity-60 font-semibold'>
{loading? item.video.channelName: <Skeleton />}
</div>
<div className='flex opacity-60 font-semibold'>
<p className='flex items-center justify-center text-center'>{loading ? item.video.viewCountText : <Skeleton />} {' '} {loading? <BsDot />: <Skeleton />}</p>
<p>{loading? item.video.publishedTimeText: <Skeleton />}</p>
</div>
</div>
</div>
</div>
)
})}
</div>
)
}
But, to create the search capability, we have to modify our header.js file to something like this:
To control the state input, declare a state
const [InputValue, setInputValue] = useState('');
And on our input field:
<input type='text' placeholder='Search'
value={InputValue}
onChange={(e) =>{
setInputValue(e.target.value)
}}
onKeyDown={(e) =>{
if (e.key === 'Enter'){
router.push(`/?query=${InputValue.toLowerCase()}`);
}}}
That's it! We built the YouTube clone. Happy coding!
Top comments (0)