20240412 react-youtube 구현

2024. 4. 12. 17:00React

<1-2교시>
youtube 틀 완성
youtube 디테일 구현 시작

https://firebase.google.com/?hl=ko
auth 소셜로그인 도와주어 api 쓰면 로그인 기능 구현 가능
리액트만 사용한다면 데이터베이스 엑세스 하는 코드만 사용하면 됨
api 제공 사이트를 많이 알면 고급진 서비스를 단시간 내에 할 수 있음
(파이어베이스 이용하라 == know fair) > 실전적이기 때문
파이어베이스 : 로그인 기능, DB 제공
(SQL이 아니라 noSQL임 : 몽고DB Not only SQL 더 큰 것을 할 수 있다. 
비정형 데이터의 강점을 가짐, 이미지 텍스트 문서 등 RDB로 하기 어려운 부분을 해소함-json형태)
자바스크립트와 궁합이 맞음 오브젝트의 어레이가 DB에 들어가 있을 때 자바스크립트에서는 json으로
json.string 하면 변환이 되고 json객체를 .parse를 하면 열어지는 편리성이 있음 - 4.15 월요일 진행

사진 업로드 시 /file/download/filename => 지금까지 사용한 방법
새로운 방법 사이트 이용 : cloudinary > 사진을 올리면 센터링 작업 사진과 관련된 여러 기능들
블러링, 하이라이팅, 인공지능과 연계 - 이미지 자체와 관련된 여러 기능을 가능하게 함

youtube ver.1 / ver.2 수정 완료 > git 에 사진 업로드 완료

채널의 제목과 정보 가져오기 (업로드) 기능 구현



 

영상 밑에 제목과 동영상 주인의 프로필 사진 가져오기 (업로드) 기능

 

VideoDetail.jsx 에 이 channelId & channelTtile이 있어야 영상 밑에 글쓴이와 제목이 뜸

 

 

큰 동영상 옆에 작은 동영상 불러오기 구현

 

 

작은 영상들 기능 구현

 

 

 

SmallVideoCard.jsx 추가 코드

 

 

 

channelInfo.jsx 수정코드

 

 

 

videos.jsx 완성본

 

나의 에러

import React from "react";
import { useParams } from 'react-router-dom';
import axios from 'axios';
import { useQuery } from '@tanstack/react-query';
import HourglassTopIcon from '@mui/icons-material/HourglassTop';
import WarningAmberIcon from '@mui/icons-material/WarningAmber';
import VideoCard from '../components/VideoCard';
import Grid from "@mui/material/Grid";



export default function Videos() {
  const { keyword } = useParams();
  const keywordUri = `https://youtube.googleapis.com/youtube/v3/search?key=${process.env.REACT_APP_YOUTUBE_API_KEY}&maxResults=25&part=snippet&q=${keyword}`;
  const popularUri = `https://youtube.googleapis.com/youtube/v3/videos?chart=mostPopular&key=${process.env.REACT_APP_YOUTUBE_API_KEY}&maxResults=25&part=snippet`;
  const { isLoading, error, data: videos } = useQuery({
    queryKey: ['videos', keyword],
    queryFn: async () => {
      const uri = keyword ? keywordUri + keyword : popularUri;
      return axios
        // .get(`/data/${keyword ? 'search' : 'popular'}.json`)
        .get(uri)
        .then(res => res.data.items);
    }, staleTime: 1000 * 60 * 1,
  });
  // useEffect(() => {
  //   axios.get(`/data/${keyword ? 'search' : 'popular'}.json`)
  //     .then(res => setVideos(res.data.items))
  // }, [keyword])
  return (
    <div>
      <div style={{ marginBottom: '10px', color: "lightcoral", padding: '0px 0px 15px 25px' }}>Videos {keyword ? `${keyword} 검색` : 'Hot Trend'}</div>
      {isLoading && <p><HourglassTopIcon />Loading</p>}
      {error && <p><WarningAmberIcon />Something is wrong!!!</p>}
      {videos && (
        <Grid container spacing={1}>
          {videos.map(video => (
            <Grid item xs={12} sm={6} md={4} lg={3}>
              <VideoCard vido={video} />
            </Grid>
          ))}
        </Grid>
        // <div style={{ textAlign: 'left', display: 'flex', flexDirection: 'row', alignItems: 'flex-start', flexWrap: 'wrap', gap: '1px', margin: '5px' }}>
        //   {videos.map((video, index) => (
        //     <div key={index} style={{ flex: 1, marginBottom: '1px', textAlign: 'left' }}>
        //       <VideoCard video={video} />
        //       <div>{video.title}</div>
        //     </div>
        //   ))}
        // </div>
      )}
    </div>
  )
}

 

수정된 코드

import React from "react";
import { useParams } from 'react-router-dom';
import { useQuery } from '@tanstack/react-query';
import axios from 'axios';
import Grid from '@mui/material/Grid';
import HourglassTopIcon from '@mui/icons-material/HourglassTop';
import WarningAmberIcon from '@mui/icons-material/WarningAmber';
import VideoCard from "../components/VideoCard";

const keywordUri = `https://youtube.googleapis.com/youtube/v3/search?key=${process.env.REACT_APP_YOUTUBE_API_KEY}&maxResults=25&part=snippet&q=`;
const popularUri = `https://youtube.googleapis.com/youtube/v3/videos?chart=mostPopular&key=${process.env.REACT_APP_YOUTUBE_API_KEY}&maxResults=25&part=snippet`;

export default function Videos() {
  const { keyword } = useParams();
  const {isLoading, error, data: videos} = useQuery({
    queryKey: ['videos', keyword],
    queryFn: async () => {
      const uri = keyword ? keywordUri + keyword : popularUri;
      return axios
              // .get(`/data/${keyword ? 'search' : 'popular'}.json`)
              .get(uri)
              .then(res => res.data.items);
              // .then(res => keyword ? res.data.items.shift() : res.data.items);
    },
    staleTime: 1000 * 60 * 1,       // 1분, ms 단위로 지정할 수 있음
  });

  return (
    <>
      {isLoading && <p><HourglassTopIcon /> Loading...</p>}
      {error && <p><WarningAmberIcon /> Something is wrong!!!</p>}
      {videos && (
        <Grid container spacing={1}>
          {videos.map(video => (
            <Grid item xs={12} sm={6} md={4} lg={3}>
              <VideoCard video={video} />
            </Grid>
          ))}
        </Grid>
      )}
    </>
  )
}

 

ChannelInfo.jsx 완성본

 

 

 

설명은 이하

주석처리 부분은 마지막에 삭제함

주서처리 부분이 youtube.js로 이동 > 한 파일에서 목데이터와 실제 데이터 on/off 기능을 하기 위함

youtube.js로 이동한 부분을 import 받아서 사용 > 코드가 간결해짐

 

 

channelInfo.jsx 최종 수정본

 

 

Videos.jsx , ChannelInfo.jsx 에서 가져옴

 

 

RelatedVideos.jsx  가져옴

 

therefore,

3가지 파일에서 각각 on/off 데이터 (목데이터, 실제데이터) 처리 하던 것을 한 곳에서 처리 > 가장 편리함

 

 

데이터 on/off 기능 따로 합친 후 Videos.jsx 최종 수정본