video_detail.jsx에 가서 iframe을 쓸 때 frameborder가 아니라 frameBorder로 바꿔 써준다. allowFullScreen도 마찬가지로 allowFullScreen으로 바꿔써준다.
app에서 작성한다. 컴포넌트가 마운트 되었을 때만 쓰고 싶다하자.
props이 바껴도 업데이트 돼야 될 이유가 없는데, 만약에 제공되는 유튜브 클라이언트가 바뀐다면 클라이언트가 바뀐다면 새로운 데이터를 받아 오고 싶을 수도 있다. 그래서 아래와 같이 app.jsx에 youtube를 전달해 줘도 된다.
useEffect(() => {
youtube
.mostPopular() //
.then(videos => setVideos(videos));
}, [youtube]);
디테일에서는 유니크한 타이틀을 가지고 있어야 된다라고 경고문이 표시되어져 있다. video_detail.jsx에 와서 title을 추가해 주면된다. 프로젝트 할때 warning이나 error 나오는지 한번씩 확인해준다.
<iframe
className={styles.video}
type="text/html"
title="youtube video player"
width="100%"
height="500px"
src={`https://www.youtube.com/embed/${video.id}`}
frameBorder="0"
allowFullScreen
그리고 video_item.jsx는 비디오나 클릭이나 디스플레이가 바뀌지 않으면 다시 렌더링 돼야 될 이유가 없다.
memo를 써서 memo안에다가 넣어준다. import 되는지 확인하고 복사해서 붙여 넣으면 된다. 이렇게 하면 아이템은 개별적으로 업데이트가 되지 않는다. 즉 props이 바뀌지 않는다면 업데이트가 될 필요가 없다면 memo를 이용하면 된다.
import React from 'react';
import styles from './video_item.module.css';
const VideoItem = memo(
({ video, video: { snippet }, onVideoClick, display }) => {
const displayType = display === 'list' ? styles.list : styles.grid;
return (
<li
className={`${styles.container} ${displayType}`}
onClick={() => onVideoClick(video)}
>
<div className={styles.video}>
<img
className={styles.thumbnail}
src={snippet.thumbnails.medium.url}
alt="video thumbnail"
/>
<div className={styles.metadata}>
<p className={styles.title}>{snippet.title}</p>
<p className={styles.channel}>{snippet.channelTitle}</p>
</div>
</div>
</li>
);
});
export default VideoItem;
search_header.jsx도 동일하게 memo를 사용해서 memo 안에다가 넣어준다.
const SearchHeader = memo(({ onSearch }) => {
const inputRef = useRef();
const handleSearch = () => {
const value = inputRef.current.value;
onSearch(value);
};
const onClick = () => {
handleSearch();
};
const onKeyPress = event => {
if (event.key === 'Enter') {
handleSearch();
}
};
console.log('Header!!!');
return (
<header className={styles.header}>
<div className={styles.logo}>
<img className={styles.img} src="/images/logo.png" alt="logo" />
<h1 className={styles.title}>Youtube</h1>
</div>
<input
ref={inputRef}
className={styles.input}
type="search"
placeholder="Search..."
onKeyPress={onKeyPress}
/>
<button className={styles.button} type="submit" onClick={onClick}>
<img
className={styles.buttonImg}
src="/images/search.png"
alt="search"
/>
</button>
</header>
);
});
memo를 쓴다는 것은 전달되는 props이 변경이 되지 않으면 re-render가 되지 않고 props이 바뀌면 다시 렌더링이 되는 것이다. onSearch가 계속 새로운 것으로 업데이트가 되면 search_header에 렌더가 계속 발생할 수 있다는 것이다.
app으로 넘어와서 app이라는 컴포넌트는 function component이기 때문에 관련된 state나 props이 바뀌면 정의한 멤버변수가 다시 만들어진다. 즉 콜백함수들이 다시 새롭게 만들어진 다는 것이다. 즉 state가 바뀔 때마다 search라는 것은 새로운 함수를 가리키게 된다.
그리고 search는 SearchHeader에 전달이 되기 때문에 새로운 props이 전달되는 거랑 동일하다. 그래서 memo를 썼지만 계속 렌더가 발생하는 것이다.
그래서 console.log("Header")를 추가해서 콘솔창을 보면 Header가 추가되는 것을 볼 수 있다. memo를 써도 props이 계쏙 바뀌면 리랜더가 발생하게 된다. 이걸 방지하고자 useCallback이라는 것을 이용할 수 있다.
useCallback을 한 단계 감싸 주고 나서 useEffect와 마찬가지로 두번째 인자에 dependency list를 전달하지 않으면 계속해서 새로운 것을 만들고 텅텅 빈 배열을 전달하면 한 번만 만들고 계속 동일한 오브젝트를 반복해서 쓴다. 그렇게 하면 Header가 출력되지 않는다.
function App({ youtube }) {
const [videos, setVideos] = useState([]);
const [selectedVideo, setSelectedVideo] = useState(null);
const selectVideo = video => {
setSelectedVideo(video);
};
const search = useCallback(query => {
setSelectedVideo(null);
youtube
.search(query) //
.then(videos => setVideos(videos));
},
[youtube]
);
useCallback 이라는것을 조심해서 사용해야 하는데 useCallback은 한번 만들면 메모리상에 계속 보관하기 때문에 메모리에 많은 영향에 갈 수가 있다. 그래서 useCallback을 정말 써야 될 때만 쓰는 것이 좋다.
사용자가 자식 컴포넌트에 props으로 전달할 때 계속 새로운 콜백을 전달하면 자식 컴포넌트가 다시 re-render가 발생할 수 있기때문에 그럴때만 useCallback을 사용해야 한다. 사용하지 않아도 될 때는 자식 컴포넌트가 아니라 JSX를 이용한 div 태그, button과 같은 이벤트를 처리하는 콜백으로 전달할 때는 새로운 게 전달되도 re-render가 발생 되지 않아서 크게 상관은 없다.
중요한 포인트는 useCallback은 사용해야 될 때와 사용하면 안 좋을 때 잘 구분해서 사용하는 것이 중요하다.
https://k-j-hyeon.github.io/Youtube_clone_coding/
App
k-j-hyeon.github.io
<출처 : DreamCoding 리액트 개념 정리+유튜브 클론코딩: ellie>
참고: https://academy.dream-coding.com/courses/react-basic
리액트 강의 (유튜브 클론 코딩 + 실시간 전송 명함 카드 만들기 웹앱 만들기)
리액트 전반적인 개념 설명과 (클래스 컴포넌트와 함수 컴포넌트 그리고 리액트 훅까지) 실전 유튜브 클론 코딩 프로젝트. Firebas의 실시간 데이터베이스를 이용해 멋진 명함 카드 만들기 웹 어
academy.dream-coding.com
'React > youtube_clone_coding' 카테고리의 다른 글
반응형 추가작업 (0) | 2021.08.17 |
---|---|
fetch web APIs & Axios library 차이점 (0) | 2021.08.16 |
video selection & detail screen (0) | 2021.08.11 |
검색 기능 Refactoring (0) | 2021.08.10 |
검색 기능 구현하기 (0) | 2021.08.10 |