프론트엔드✏️/개인공부

[youtube] tailwind, react-router, popular list, search

당근먹는하니 2023. 1. 12. 14:47
728x90
반응형

yarn add -D @tailwindcss/line-clamp

유튜브 제목이 두 줄까지만 나오고 그 뒤는 ...(말줄임표) 처리 되도록 하기 위해서 line-clamp 플러그인을 깔았다.

// tailwind.config.js

module.exports = {
  content: ["./src/**/*.{html,js,jsx,ts,tsx}"],
  theme: {
    extend: {
      spacing: {
        1: "1px",
        2: "2px",
      },
    },
  },
  plugins: [require("@tailwindcss/line-clamp")], // 이 부분 추가
};

plugins에 line-clamp를 추가한다.

line-clamp-{n} 이렇게 적어주면 된다!
그리고 h도 지정을 해줘야 한다.

이렇게 두 줄까지만 보이고 말 줄임표가 생겼다!



누르면 영상 링크로 가게 하고 싶은데 그걸 못 찾겠다.
아, 데이터에서 하나하나 가져오는 게 아니라 iframe으로 가져오면 되는건가?

일단 인기 목록 받아오기

const {
    isLoading,
    error,
    data: popularVideos,
  } = useQuery(
    ["videos", "main"],
    async () => {
      return fetch(
        `https://youtube.googleapis.com/youtube/v3/videos?part=snippet&chart=mostPopular&regionCode=KR&maxResults=25&key=${apiKey}`
      ).then((res) => res.json());
    },
    {
      staleTime: 1000 * 60 * 3,
    }
  );

골자는 fetch 뒤의 주소의 mostPopular
regionCode는 국가 설정
apiKey는 .env에 REACT_APP_YOUTUBE_API_KEY 로 저장해서 갖고 왔다.

ㅎ아까 설정한 일립스가 민망하게 찌부되어 나왔다.

굳이 완전히 똑같이 따라할 필요는 없겠지만 가이드라인이 필요해서,, 갖고 왔다. 강의 메인에도 나와있는 화면이니 괜찮겠지?!
이제 이걸 따라해볼건데 지금 되는 거라곤 썸네일과 이름 불러오기 뿐...

아까 플러그인 깔아서 두 줄로 했잖아...! 왜 안돼?
그리고 지금 popularVideos로 해놨는데 어째서 시츄 검색 영상이 나오는지...
그리고 동네 고양이가 어쩌구 저 영상 보고 싶다ㅠ

유튜브 로고는 여기에서 가져왔다.
https://www.youtube.com/howyoutubeworks/resources/brand-resources/#logos-icons-and-colors

YouTube Brand Resources and Guidelines - How YouTube Works

Explore our brand resources to learn the guidelines of the use and application of the YouTube brand and access our Brand Request Form.

www.youtube.com


아 저거 두 줄이 아니라 한 줄에서 잘라버리는거

truncate 라는 속성을 써놔서 그런 거였다. 


테일윈드 속성을 모르니까 계속 검색해서 써야하는데 너무 편하니까 재밌다



비디오 뭉치를 클릭하면 페이지 이동을 시키고 그 페이지 이동시킨 곳에서 iframe을 써서 동영상을 가져와서 보여줘야겠다.
react-router..자신이 없어...

yarn add react-router-dom


이거 한 후에 index.js를 건들여야하는건지 App.js를 건들여야하는건지에서 엄청 헤맸다.

// App.js
import "./App.css";
import { ReactQueryDevtools } from "react-query/devtools";
import { QueryClient, QueryClientProvider } from "react-query";
import Layout from "./components/commons/layout";
import Home from "./components/units/home/Home";
import {
  BrowserRouter,
  createBrowserRouter,
  RouterProvider,
} from "react-router-dom";
import Video from "./components/units/video/Video";
import Root from "./components/commons/layout/Root";

const queryClient = new QueryClient();
const router = createBrowserRouter([
  {
    path: "/",
    element: <Root />,
    errorElement: (
      <div className="mx-auto h-screen bg-slate-700 text-white">
        미안해요🥲오류가 났어요
      </div>
    ),
    children: [
      {
        index: true,
        path: "/videos",
        element: <Home />,
      },
      {
        index: true,
        path: "/video",
        element: <div>HIHIHI</div>,
      },
    ],
  },
]);

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <RouterProvider router={router} />
      <ReactQueryDevtools initialIsOpen={false} />
    </QueryClientProvider>
  );
}

export default App;

이렇게 쓰고 index.js는 건들지 않았다.

import React from "react";
import { Outlet } from "react-router-dom";
import Layout from ".";

export default function Root() {
  return (
    <div>
      <Layout>
        <Outlet />
      </Layout>
    </div>
  );
}

{children}을 받는 Layout 안에 Outlet을 써주니 문제없이 된다.

얼렁뚱땅이지만... 좀 되고 있는 것 같지 않나?!?!!!!

이제 클릭하면 동적 라우팅을 이용해서 그 video 아이디의 페이지로 가보게 하겠다,..

VideoDetail 페이지를 만들고

 {
        index: true,
        path: "/video/:id",
        element: <VideoDetail />,
      },

추가한다. 그럼 /video/adqweasdaf아무거나 써도 VideoDetail 창이 뜬다!

그럼 video 뭉치에 링크를 걸면 끝 ?

import React from "react";
import { useQuery } from "react-query";
import { Link } from "react-router-dom";

export default function Video({ category }) {
  return (
    <>
      {category?.items?.map((video) => (
        <div id={video.id}>
          <Link to={`/video/${video.id}`}>
            <img src={video.snippet.thumbnails.high.url} alt="thumbnail" />
            <div className="h-10 text-sm font-bold line-clamp-2">
              {video.snippet.title}
            </div>
            <div className="pt-3 text-xs">{video.snippet.channelTitle}</div>
          </Link>
        </div>
      ))}
    </>
  );

이렇게 Link를 추가해줬다.



그럼 이제 디테일 페이지에서 useParams을 통해 뽑은 아이디로 영상을 보여주자!!!

<iframe
        id="player"
        type="text/html"
        width="640"
        height="360"
        src="http://www.youtube.com/embed/M7lc1UVf-VE?enablejsapi=1&origin=http://example.com"
        frameborder="0"
        title="hi"
      ></iframe>

이걸 복붙해서 넣어주니

뿅 생겼다.

근데 iframe으로 불러오는 건 자유도가 떨어진다고 함

const onYouTubeIframeAPIRedy = () => {
    let player = new YT.Player("player", {
      height: "360",
      width: "640",
      videoId: "M7lc1UVf-VE",
      events: {
        onReady: onPlayerReady,
        onStateChange: onPlayerStateChange,
      },
    });
  };

그래서 이 방식을 쓰려고 하는데 !!!! new YT.Player가 어디서 온건데...?? ㅠㅠ

리액트에선 iframe방법밖에 못 쓰나? 설마? 설마? 그래서 그냥 iframe 으로 넣었다~~^^
그럼 이제 onReady 같은 함수는 못 쓰는거야..??


검색을 어떻게 구현하면 좋을까?
검색을 하면 라우팅은 /search/:keyword 이런식으로 하면 될 것 같은데

1. 검색창이 있는 헤더에서 keyword를 입력받고, 받으면 /search/:keyword로 보낸다.

import React, { useState } from "react";
import { Link, useNavigate } from "react-router-dom";

export default function Header() {
  const navigate = useNavigate();

  const [keyword, setKeyword] = useState("");

  const handleChange = (e) => {
    setKeyword(e.target.value);
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    setKeyword("");
    navigate(`/search/${keyword}`);
  };
  return (
      <form onSubmit={(e) => handleSubmit(e)}>
        <input
          className="w-3/6 bg-white "
          value={keyword}
          onChange={(e) => handleChange(e)}
        />
      </form>
    </div>
  );
}



2. 검색한 목록들 불러올 페이지에서 useParams로 키워드를 뽑고 그 키워드로 검색 요청한다.

// SearchVideo.jsx 

import React from "react";
import { useQuery } from "react-query";
import { useParams } from "react-router-dom";
import Video from "../video/Video";

export default function SearchVideo() {
  const { keyword } = useParams();
  const apiKey = process.env.REACT_APP_YOUTUBE_API_KEY;

  const {
    isLoading,
    error,
    data: searchVideos,
  } = useQuery(
    ["videos", "main"],
    async () => {
      return fetch(
        `https://youtube.googleapis.com/youtube/v3/search?part=snippet&maxResults=25&q=${keyword}&key=${apiKey}`
      ).then((res) => {
        return res.json();
      });
    },
    {
      staleTime: 1000 * 60 * 3,
    }
  );
  return (
    <div className="w-full bg-gray-800 text-white">
      <div className="grid grid-cols-5 gap-2">
        <Video category={searchVideos} />
      </div>
    </div>
  );
}


일단 여기까지...하고 좀만 쉴래

728x90
반응형