DEV Community

Cover image for Let's build a Youtube clone with Nextjs and Tailwindcss 🎉(Part 3)
Sadeedpv🥇
Sadeedpv🥇

Posted on • Edited on

Let's build a Youtube clone with Nextjs and Tailwindcss 🎉(Part 3)

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
      }
    }

  }
}
Enter fullscreen mode Exit fullscreen mode

So, now to access the data, all you have to do is:

export default function Home({data}){
}
Enter fullscreen mode Exit fullscreen mode

and Pass the data to the body component:

<Body data={data} /> 
Enter fullscreen mode Exit fullscreen mode

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>
  )
}
Enter fullscreen mode Exit fullscreen mode

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'
Enter fullscreen mode Exit fullscreen mode

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>
  )
}
Enter fullscreen mode Exit fullscreen mode

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('');
Enter fullscreen mode Exit fullscreen mode

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()}`);
}}}
Enter fullscreen mode Exit fullscreen mode

That's it! We built the YouTube clone. Happy coding!

Top comments (0)