본문 바로가기
Project/REACT

21 - 영화 앱에 기능 추가하기 (2)

by Elfen Lied 2020. 12. 24.
반응형

1. 내비게이션 만들기

- Navigation 컴포넌트 만들기

components 폴더에 Navigation.js 파일 만든다.

import React from 'react';

function Navigation() {
  return (
    <div>
      <a href="/">Home</a>
      <a href="/about">About</a>
    </div>
  );
}

export default Navigation;

이대로 Navigation 컴포넌트를 App 컴포넌트에 포함시키면 문제가 생긴다.

 

- Navigation 컴포넌트 App 컴포넌트에 포함시키기

App.js 를 보자.

Navigation.js를 임포트 하고, <HashRouter> 사이에 포함시킨다.

.
.
import About ...
import Navigation from './components/Navigation';  // 여기 추가

function App() {
  return (
    <HashRouter>
      <Navigation />  // 여기 추가
      .
      .
      .
    </HashRouter>
  );
}

앱 실행하면 Home, About 링크(a 엘리먼트)를 확인할 수 있다.

눌러보면 잘 작동하는거 같지만,

누를 때마다 리액트가 죽고, 새 페이지가 열린다. (새로고침 되는 문제)

a 엘리먼트의 href 속성은 페이지 전체를 다시 그림.

해결하기 위해서 react-router-dom 의 Link 컴포넌트를 사용하면 됨.

 

- a 엘리먼트 Link 컴포넌트로 바꾸기

Navigation 컴포넌트에 Link 컴포넌트를 임포트 한다.

그다음 a 엘리먼트를 Link 컴포넌트로 바꾼다.

href 속성은 to로 바꿈.

Navigation.js 를 보자.

import React from 'react';
import { Link } from 'react-router-dom';

function Navigation() {
  return (
    <div>
      <Link to="/">Home</Link>
      <Link to="/about">About</Link>
    </div>
  );
}

export default Navigation;

앱 실행하고 Home, About 링크를 눌러보자.

Home 상태에서 Home을 눌러도 새로고침 안된다.

 

About도 잘 나온다.

About 일 때 Home 을 누르면 Loading.. 뜨고 화면 나타나는 건 정상.

 

지금까지 기억할 것은 Link, Router 컴포넌트는

반드시 HashRouter 안에 포함되어야 한다.

 

- Navigation 컴포넌트 스타일링하기

components 폴더에 Navigation.css 만든다.

코드 블록처럼 작성하고 Navigation 컴포넌트에 임포트 한다.

Navigation.css 을 보자.

.nav {
  z-index: 1;
  position: fixed;
  top: 50px;
  left: 10px;
  display: flex;
  flex-direction: column;
  background-color: white;
  padding: 10px 20px;
  box-shadow: 0 13px 27px -5px rgba(50, 50, 93, 0.25),
    0 8px 16px -8px rgba(0, 0, 0, 0.3), 0 -6px 16px -6px rgba(0, 0, 0, 0.025);
  border-radius: 5px;
}

@media screen and (max-width: 1090px) {
  .nav {
    left: initial;
    top: initial;
    bottom: 0;
    width: 100%;
  }
}

.nav a {
  text-decoration: none;
  color: #0008fc;
  text-transform: uppercase;
  font-size: 12px;
  text-align: center;
  font-weight: 600;
}

.nav a:not(:last-child) {
  margin-bottom: 20px;
}

 

Navigation.js 를 보자.

import React from 'react';
import { Link } from 'react-router-dom';
import './Navigation.css';  // 여기 추가

function Navigation() {
  return (
    <div className="nav">  // className 추가
      <Link to="/">Home</Link>
      <Link to="/about">About</Link>
    </div>
  );
}

export default Navigation;

앱 실행 후 브라우저 화면 크기를 줄이거나 늘려보자.

 

 

2. 영화 상세 정보 기능 만들기

영화 카드를 눌렀을 때 상세 정보가 뜨는 기능을 만든다.

이 기능은 route props 를 반드시 이해해야 한다.

route props 는 라우팅 대상이 되는 컴포넌트에 넘겨주는 기본 props 다.

 

- route props 살펴보기

console.log() 를 통해 About 로 어떤 props 가 넘어오는지 보자.

About.js 를 보자.

.
.
.
function About(props) {  // props 인자 추가
  console.log(props);    // console.log() 추가
  return (
    <div className="about__container">
      <span>
        "Freedom is the freedom...
        .
        .
        .

앱 실행 후 About 으로 가서 개발자 도구 console 탭을 보자.

이게 react-router-dom 에서 Route 컴포넌트가 그려줄 컴포넌트에 전달한 props 다.

 

주목할 점은 Route 컴포넌트가 그려줄 컴포넌트에는 항상 이 props가 전달되고,

이 props에 마음대로 데이터를 담아 보낼 수 있다.

 

- route props 에 데이터 담아 보내기

route props 에 데이터를 담아 보내려면 Navigation 컴포넌트에 있는

Link 컴포넌트의 to props 의 구조를 조금 바꾼다.

Navigation 컴포넌트 /about 로 보내주는 Link 컴포넌트의 to props 를 수정하자.

Navigation.js 를 보자.

function Navigation() {
  return (
    <div className="nav">
      <Link to="/">Home</Link>
      <Link to={{ pathname: '/about', state: { fromNavigation: true }}}>About</Link>
    </div>
  );
}

to props 에 객체 전달함.

pathname 은 URL을 뜻함.

state 는 route props 에 보내줄 데이터를 뜻함.

 

- route props 다시 살펴보기

/about 로 간 다음 개발자 도구 console 탭에서 location 을 펼쳐 보자.

state 키에 보내준 데이터를 확인할 수 있다.

 

- Navigation 컴포넌트 정리하기

Navigation 컴포넌트를 원래대로 돌린다.

Navigation.js 를 보자.

function Navigation() {
  return (
    <div className="nav">
      <Link to="/">Home</Link>
      <Link to="/about">About</Link>  // 원래대로 돌려줌
    </div>
  );
}

 

- Movie 컴포넌트에 Link 컴포넌트 추가

Movie 컴포넌트에 Link 컴포넌트를 임포트 한다.

Link 컴포넌트에 to props 를 작성한다.

여기서 Link 컴포넌트의 위치에 주의하자.

Movie.js 를 보자.

function Movie({ title, year, summary, poster, genres}) {
  return (
    <div className="movie">
      <Link   // 여기 추가.
        to={{
          pathname: '/movie-detail',
          state: { year, title, summary, poster, genres },
        }}
      >
        <img src={poster} alt={title} title={title} />
        .
        .
        .
          <p className="movie__summary">{summary.slice(0, 180)}...</p>
        </div>
      </Link>  // 여기에 Link 를 닫아준다.
    </div>
  );
}

앱 실행해서 영화 카드 누르면 /movie-detail 로 이동된다.

이제 movie-detail에 보여줄 화면을 만든다.

 

- Detail 컴포넌트 만들기

routes 폴더에 Detail.js 를 생성한다.

그리고 Detail 컴포넌트에서 Movie 컴포넌트의 Link 컴포넌트가 보내준

영화 데이터(state: {year, title, summary, poster, genres}) 를 확인할 수 있게

console.log()도 작성해 준다.

Detail.js 를 보자.

import React from 'react';

function Detail(props) {
  console.log(props);
  return <span>hello</span>;
}

export default Detail;

아직 Detail 을 출력해 줄 Route 컴포넌트를 추가하지 않아서,

console.log(props) 는 확인할 수 없다.

App.js 에서 Route 컴포넌트를 마저 추가하자.

 

- Route 컴포넌트 추가

App.js 를 열고 Detail 컴포넌트를 임포트 한다.

Route 컴포넌트에서 Detail 컴포넌트를 그려주도록 작성한다.

App.js 를 보자.

.
.
.
import Navigation...
import Detail from './routes/Detail'; // 여기 임포트.

function App() {
  return (
    <HashRouter>
      <Navigation />
      <Route path="/" exact={true} component={Home} />      
      <Route path="/about" component={About} />
      <Route path="/movie-detail" component={Detail} />  // 여기 추가.
    </HashRouter>
  );
}

 

- 영화 카드 눌러 /movie-detail 로 이동한 다음 데이터 확인하기

영화 카드 눌러 /movie-detail 로 이동.

화면에는 Detail 컴포넌트가 출력하는 hello 가 보인다.

개발자 도구 console 탭을 보면 [location --> state] 에

Movie 컴포넌트에서 Link 컴포넌트를 통해 보내준 데이터가 들어있다.

 

- /movie-detail 로 바로 이동하기

URL에 직접 /movie-detail 입력해서 바로 이동해 보자.

개발자 도구 console 탭을 보면 hello는 뜨지만 데이터는 없다.

state: undefined 가 보인다.

이런 경우 사용자를 강제로 Home 으로 돌려보내야 한다.

그 기능이 리다이렉트 기능이다.

 


여기까지 종합

Navigation 만들고 a 엘리먼트 사용.

a 엘리먼트의 href 기능을 Link to 로 바꿔서 새로고침 현상 없애기.

Link, Router 컴포넌트는 반드시 HashRouter 사이에 입력한다.

route props 는 라우팅 대상이 되는 컴포넌트에 넘겨주는 기본 props 다.

반응형

댓글