[Clone YouTube] React Router
리액트에서 페이지를 이동하는 방법을 찾다가 React Router에 대해 알게 되었다. 사실 이전에 강의를 들으며 Movie App을 만들 때 사용해 보기는 했으나... 잊고 있었다.
import React from "react";
import { Route, BrowserRouter as Router } from "react-router-dom";
import Main from "./components/Main";
import Playing from "./components/routes/Playing";
const App = () => {
return (
<Router>
<Route exact path="/" component={Main} />
<Route path="/playing/:videoName" component={Playing} />
</Router>
);
};
export default App;
우선 라우터를 사용하기 위해 App.js를 위와 같이 만들었다. 최대한 많은 페이지를 구현해 보고 싶은데, 우선은 가장 기본이 될 페이지인 메인 페이지와 동영상 재생 페이지만을 구현했다. Main 페이지를 루트 페이지로 만들기 위해 path를 /로 주고, excat 옵션을 사용해 다른 페이지에 /가 포함되더라도 Main 페이지가 겹쳐 보이지 않게 했다. 두 번째 페이지인 Playing 페이지는 path를 /playing으로 주었고, 클릭되는 동영상에 따라 동영상이 표시되어야 하므로 url 파라미터로 videoName을 전달했다.
import React from "react";
import styled from "styled-components";
import VideoExplanaion from "./videoExplanaion/VideoExplanaion";
import { Link } from "react-router-dom";
const VideoBoxWrap = styled.li`
list-style: none;
max-width: 359px;
max-height: 298px;
min-width: 250px;
min-height: 140px;
width: 23%;
margin: 0 8px 40px 8px;
video {
width: 100%;
height: 60%;
background-color: black;
}
:hover {
cursor: pointer;
}
:hover .fa-ellipsis-v {
display: flex;
}
`;
const onMouseEnterVideo = (e) => {
e.target.play();
};
const onMouseOutVideo = (e) => {
e.target.pause();
e.target.currentTime = 0;
};
const VideoSummary = ({ videoName }) => {
return (
<VideoBoxWrap>
<Link to={`/playing/${videoName}`}>
<video
src={`/videos/${videoName}.mp4`}
onMouseEnter={onMouseEnterVideo}
onMouseOut={onMouseOutVideo}
muted={true}
/>
</Link>
<VideoExplanaion />
</VideoBoxWrap>
);
};
export default VideoSummary;
비디오나 제목 등의 클릭을 통해 Playing 페이지로 이동할 것이므로 VideoSummary 컴포넌트에서 Router의 Link를 건다. react-router-dom으로부터 Link를 import한다. 또, 현재는 부모 요소인 VideoBox에 videoName들이 정의되어 있으므로, 이를 props로 전달받았고, 이렇게 전달 받은 videoName을 다시 Link의 path의 videoName으로서 전달하게 된다.
import React from "react";
import Header from "../headerComponents/Header";
import styled from "styled-components";
const StyledColumnsWrap = styled.div`
top: 56px;
width: calc(100vw - 56px - 60px);
height: 100%;
position: relative;
display: flex;
flex-direction: row;
`;
const PrimaryWrap = styled.div`
flex: 7;
padding: 24px 24px 0 0;
margin-left: 24px;
video {
width: 100%;
}
`;
const PlayerWrap = styled.div`
max-width: 1280px;
max-height: 720px;
`;
const Playing = ({ match }) => {
const { params } = match;
return (
<>
<Header />
<StyledColumnsWrap>
<PrimaryWrap>
<PlayerWrap>
<video src={`/videos/${params.videoName}.mp4`} controls />
</PlayerWrap>
</StyledColumnsWrap>
</>
);
};
export default Playing;
Link로부터 전달받은 match를 콘솔로 확인해 보면 아래와 같이 path, url, isExact, params가 포함되어 있다.
이 중, params에는 videoName 변수가 전달되어 있고, 이 값으로는 클릭한 동영상의 이름이 할당되어 있다. 따라서 video의 src를 params.videoName으로 설정해 두면, 클릭한 동영상의 이름을 받아서 해당 동영상을 불러오게 된다.
이 과정에서 저 video의 src 경로 때문에 시간을 많이 소비하고 말았는데, 루트 경로를 ./로 설정했기 때문에 발생했다. /videos/${params.videoName}.mp4 혹은 한 번 더 내려가서 ../videos/${params.videoName}.mp4로 설정했더니 영상이 나타났다.