app이라는 컴포넌트 안에, video 리스트라는 컴포넌트를 만들어서, 컴포넌트 안에 각각의 비디오 아이템을 보여주면 된다.
박스 구조로 나타내면 이런 형식이다. 비디오 리스트 컴포넌트 안에 각각의 비디오 아이템 상자가 있는 모습이다.
처음에는 온전한 카드 형식보다 일단 간단한 타이틀만 보여질 수 있도록 가져와본다.
우선, app이라는 컴포넌트가 사용자에게 보여질 때 유튜브로부터 데이터를 받아와야 한다.
일단 그러기 위해서는 데이터를 받아와서 저장할 수 있는 state 가 있어야 한다.
간단하게 react hook을 사용하면 useState() 를 사용하면 된다.
const [videos, setVideos] = useState([]) 를 통해서 videos를 저장하고, setVideos를 통해 비디오를 업데이트 할 수 있게 만들어준다.
초기값은 [] 로 텅텅 비어진 비디오의 목록을 초기값으로 설정한다.
또, useEffect()를 사용해서 컴포넌트가 업데이트 될 때, 보여질 때마다 호출되도록 만들어준다.
인자값을 아무것도 두지 않으면, 계속 마운트 될 때마다 호출이 되기 때문에 [] 빈 배열로 인자값을 둔다.
참고로 빈 배열은, 처음 한 번 마운트 될 때만 호출한다는 뜻
우리가 그 때 postman에 만들어 놓은 query들 대로 코드를 눌러보면 javascript fetch 부분이 있다.
var requestOptions = {
method: 'GET',
redirect: 'follow'
};
fetch("https://youtube.googleapis.com/youtube/v3/videos/?part=snippet&chart=mostPopular&maxResult=25&key=KEY", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
postman에 code를 클릭하면 여러가지가 뜨고, 이렇게 fetch 를 불러올 수 있는데, 이것을 복사해서 우리의 프로젝트에 사용하면 된다.
방금 만든 useEffect 안에 간단하게 붙여 넣으면 된다.
requestOptions은, 그냥 options을 전달해주는 것이다.
우리가 간단하게 작업을 하려면 response.text 보다는, json으로 변환해주면 좋다.
그리고, console을 확인해보면, 우리가 필요한 것은 items 인 것을 볼 수 있다. (items 안에 정보가 들어가 있음)
이렇게 result.items를 우리가 아까 만들어 둔 useState의 setVideos로 업데이트 해준다.
그 다음 video_item과 video_list 파일을 생성해준다.
rsi를 입력해서 react 틀을 만들어준다.
import React from 'react';
const VideoItem = props => <h1>{props.title}</h1>
export default VideoItem;
이렇게 간단하게 video_item에 타이틀을 props로 받아오는 h1 태그를 만들었다.
import React from 'react';
const VideoList = (props) => (
<ul>
{props.videos.map(video => <VideoItem/>)}
</ul>
export default VideoList
video_list 에는 props에서 받아온 video를 map으로 돌려서 video 각각 별로 videoItem에 넣어주는 태그를 만들었다.
list 형식으로 보여주어야 하기 때문에 unorder list ul 태그를 사용했다.
app.jsx
return <VideoList videos={videos};
props를 받을 app.jsx 로 가서 VideoList를 import 한 다음, videos 라는 props를 만들어 준 후, 안에는 useState에 저장해놓은 videos를 넘겨준다.
전달된 props를 확인할 때는, 콘솔창의 component에 가서 맞게 데이터가 왔는 지, 데이터의 형식은 어떤 지를 확인해야 한다.
여기서는, 우리가 video_item을 받아올 때 그냥 props.title로 받아왔는데, 그러면 되지 않고
snippet 에 title이 있는 것을 볼 수 있으므로
props.video.snippet.title 로 해야 불러올 수 있는 것을 볼 수 있다.
그러면, 브라우저 화면에 이렇게 title 이 나오는 것을 볼 수 있다.
이제 정말 비디오 list를 만들 수 있도록 video_item에서 하나하나 데이터를 불러와서 하나의 카드를 만드는 작업을 해야 한다.
<li>태그로 감싼 후에 우선 썸네일을 가져와야 하기 때문에, snippet에 있는 thumbnail을 가져온다.
이 썸네일은 img 이기 때문에 img 태그를 사용한다.
<li>
<img
src={props.video.snippet.thumbnails.medium.url}
alt="video thumbnail"
/>
</li>
이렇게 src로 썸네일의 url을 가져온다.
이제 채널 이름과, 타이틀과 채널 타이틀을 가져온다.
<div>
<p>{props.video.snippet.title}</p>
<p>{props.video.snippet.channelTitle}</p>
</div>
이렇게 div로 묶어서 (css style 적용을 위해) 데이터들을 가져온다.
* 이렇게 계속 props.video.snippet 이 조금 번거롭다면, 우리는 앞의 props에서 destructing가 가능하다.
인자에서, props 안에 있는 video를 열어서 받아볼 수 있다.
const VideoItem = ({video}) => {
}
이렇게 props 안에 있는 video를 가져올 수 있다.
만약에 video를 가져올 건데, 여기서는 다른 이름으로 사용하고 싶다면,
const VideoItem = ({video: videoItem}) => {
}
이런식으로 videoItem으로 사용할 수 있도록 만들 수도 있다. (video를 가져오는 것은 똑같다)
하지만 우리는 video.snippet 자체가 반복되기 때문에 그냥 snippet 만 쓸 수 있다.
그럼 또 destructing 해주면 된다.
const VideoItem = ({video : { snippet }}) => {
}
이렇게 해주면, 우리가 사용할 때
const VideoItem = ({video : {snippet}}) => {
<li>
<img src={snippet.thumbnails.medium.url}/>
<div>
<p>{snippet.title}</p>
<p>{snippet.channelTitle}</p>
</div>
</li>
}
이런식으로 snippet 만 사용해서 접근해서 쓸 수 있다.
이 구조로 작업을 했다면, 이제 css 작업을 해야 한다.
저번에 했던 postcss 구조로 module을 만들어서 작업하면 좋다
일단 video_litem_module.css 파일을 만든다.
그리고 video_item.jsx 에서 styles로 import 한다.
import React from "react";
import styles from "./video_item.module.css";
const Video = ({) => {
const { video, onVideoClick } = props;
return (
<li className={styles.container} onClick={() => onVideoClick(video)}>
<div className={styles.video}>
<img
src={video.snippet.thumbnails.medium.url}
className={styles.thumbnail}
alt="video thumbnail"
></img>
<div className={styles.metadata}>
<p className={styles.title}>{video.snippet.title}</p>
<p className={styles.channel}>{video.snippet.channelTitle}</p>
</div>
</div>
</li>
);
};
export default Video;
이렇게 style 적용을 해준다.
.container {
width: 50%;
padding: 0.2em;
}
.video {
display: flex;
align-items: center;
border: 1px solid lightgray;
box-shadow: 3px 3px 5px 0px rgba(191, 191, 191, 0.53);
cursor: pointer;
transition: transform 250ms ease-in;
}
.video:hover {
transform: scale(1.02);
}
.thumbnail {
width: 40%;
height: 100%;
}
.metadata {
margin-left: 0.2em;
}
.title,
.channel {
margin: 0;
font-size: 0.8rem;
}
.channel {
font-size: 0.6rem;
}
'React' 카테고리의 다른 글
react youtube-clone 비디오 선택 & 상세화면 (0) | 2022.09.29 |
---|---|
react youtube-clone search api를 이용하여 검색 기능 구현하기 (0) | 2022.09.28 |
react youtube-clone postman 소개와 설정 (0) | 2022.09.28 |
react youtube-clone youtube apis 살펴보기 (0) | 2022.09.28 |
react youtube-clone api 키 설정하기 (0) | 2022.09.27 |