만들면서 배우는 리액트 튜토리얼 - 3.Props

by - August 17, 2018


Related image


리액트의 주요 컨셉으로 크게 Prop과 State가 있는데

오늘 배울 것은 이 중 하나인 Prop이다.

Image result for react props


Image result for react props





















State와 Props의 차이



Movie App을 구현할 때 메인 컴포넌트 App은 

API를 쓰든 하드코딩으로 직접 데이터를 만들든 모든 영화 데이터를 가지고 있어야하고

이 영화들은 Movie Card 형태로 보여질 것이다.

즉, 메인 컴포넌트가 영화 데이터를 리스트 같은 형태로 갖고있어야 한다는 뜻이다.


또 리스트 안의 Movie Card에는 해당 영화의 상세 정보(Movie Poster 등)가 각각 담길 것이다.

즉, 부모 컴포넌트가 자식 컴포넌트에게 각 정보를 전달해 준다는 뜻인데,

이 Props가 바로 대표적으로 부모가 자식에게 정보를 줄 때 사용하는 컨셉이다.

1.1. Props 기본 예시

import React, { Component } from 'react';
import './App.css';
import Movie from './Movie'

const movies = [
  "Matrix",
  "Full Metal Jacket",
  "Oldboy",
  "Start Wars",
]
class App extends Component {
  render() {
    return (
      <div className="App">
        <Movie title={movies[0]}/>
        <Movie title={movies[1]}/>
        <Movie title={movies[2]}/>
        <Movie title={movies[3]}/>
      </div>
    );
  }
}

export default App;
App.js

import React, { Component } from 'react';
import './Movie.css';

class Movie extends Component {
    render() {
        console.log(this.props);
        return(
            <div>
                <MoviePoster />
                <h1>Hello this is a movie</h1>
            </div>
        )
    }
}

class MoviePoster extends Component {
    render() {
        return(
            <img src='https://m.media-amazon.com/images/M/MV5BMTM0NjQ4OTgyNV5BMl5BanBnXkFtZTcwOTU2MzQ4Nw@@._V1_.jpg'/>
        )
    }
}

export default Movie;
Movie.js
  

App.js에서 movies라는 이름으로 영화 제목들이 담긴 배열을 만들고

Movie 컴포넌트를 render()에서 return 할 때

<div className="App">
  <Movie title={movies[0]}/>
  <Movie title={movies[1]}/>
  <Movie title={movies[2]}/>
  <Movie title={movies[3]}/>
</div>

위와 같이 title이라는 이름의 객체 형태로 넣어서 함께 보내주는 것을 볼 수 있다.

이 객체가 바로 prop인데

이를 받은 Movie 컴포넌트는 {this.prop}를 통해 이 데이터를 이용할 수 있다.

class Movie extends Component {
  render() {
    return(
      <div>
        <MoviePoster />
        <h1>{this.props.title}</h1>
      </div>
    )
  }
}

1.2. Props 활용 예시

import React, { Component } from 'react';
import './App.css';
import Movie from './Movie'

const movieTitles = [
  "Matrix",
  "Full Metal Jacket",
  "Oldboy",
  "Star Wars",
]

const movieImages = [
  "https://images-na.ssl-images-amazon.com/images/I/51vpnbwFHrL._SY445_.jpg",
  "https://i.pinimg.com/originals/36/1e/cd/361ecdb85a3767f70810cbe2cdaaf1a4.jpg",
  "https://m.media-amazon.com/images/M/MV5BYjQwZTc3ODktZjk1ZS00N2Y3LWFlYmUtMmQ4M2IwMjZlYTIwXkEyXkFqcGdeQXVyNjQwMzk1MDM@._V1_.jpg",
  "http://cdn.shopify.com/s/files/1/0151/0741/products/Star_Wars_Portrait-NGPS1263_Copy_1024x1024.jpg?v=1504676565",
]

class App extends Component {
  render() {
    return (
      <div className="App">
        <Movie title={movieTitles[0]} poster={movieImages[0]}/>
        <Movie title={movieTitles[1]} poster={movieImages[1]}/>
        <Movie title={movieTitles[2]} poster={movieImages[2]}/>
        <Movie title={movieTitles[3]} poster={movieImages[3]}/>
      </div>
    );
  }
}

export default App;
App.js


import React, { Component } from 'react';
import './Movie.css';

class Movie extends Component {
  render() {
    return(
      <div>
        <MoviePoster poster={this.props.poster}/>
        <h1>{this.props.title}</h1>
      </div>
    )
  }
}

class MoviePoster extends Component {
  render() {
    return(
      <img src={this.props.poster}/>
    )
  }
}

export default Movie;
Movie.js


App.js에 movieImages라는 이름으로 영화 포스터 배열을 만들고

Movie컴포넌트를 render할 때 이번에는 poster={movieImage[0]} 명령어를 더해

poster라는 이름의 객체 형태로 movieImages  props를 보내준다.

그럼 이제 Movie 컴포넌트는 {this.props.poster} 명령어로 해당 데이터를 이용할 수 있다.

하지만 Movie 포스터는 이 props를 전달해주기 위해 받은 것일 뿐

실제로 poster를 사용할 컴포넌트는 MoviePoster 이므로 

이번에는 Movie컴포넌트에서 MoviePoster 컴포넌트로 이 props를 보내준다.

그러면 이제 moviePoster 컴포넌트도 {this.props.poster} 명령어로 

포스터 데이터를 이용할 수 있게 된다.


정리하자면 영화 타이틀과 포스터 정보를 메인(App.js)에 다 집어넣고 

그것을 각 컴포넌트에 props로 전달하여 해당 정보를 출력하는 것이다.

1.3.  Array.map()

import React, { Component } from 'react';
import './App.css';
import Movie from './Movie'

const movies = [
  {
    title:"Matrix",
    poster:"https://images-na.ssl-images-amazon.com/images/I/51vpnbwFHrL._SY445_.jpg",
  },
  {
    title:"Full Metal Jacket",
    poster:"https://i.pinimg.com/originals/36/1e/cd/361ecdb85a3767f70810cbe2cdaaf1a4.jpg",
  },
  {
    title:"Oldboy",
    poster:"https://m.media-amazon.com/images/M/MV5BYjQwZTc3ODktZjk1ZS00N2Y3LWFlYmUtMmQ4M2IwMjZlYTIwXkEyXkFqcGdeQXVyNjQwMzk1MDM@._V1_.jpg",
  },
  {
    title:"Star wars",
    poster:"http://cdn.shopify.com/s/files/1/0151/0741/products/Star_Wars_Portrait-NGPS1263_Copy_1024x1024.jpg?v=1504676565",
  },
]

class App extends Component {
  render() {
    return (
      <div className="App">
         {/*
movies.map을 하면 movie에 movies의 객체가 하나씩 들어가고
화살표 다음 내용을 리턴한다
*/}
        {movies.map(movie =>
          <Movie title={movie.title} poster={movie.poster} />
        )}

        {/*
        {
          movies.map(function(movie) {
            return <Movie title={movie.title} poster={movie.poster} />
          })
        }
*/}
      </div>
    );
  }
}

export default App;



1.2.과 1.3.에서 <div className="App">은 같은 동작을 수행한다.

map 메소드에 익숙하지 않은 사람은 조금 헷갈릴 수 있는데

for in 문과 비슷한 느낌이라고 보면 된다.


위 코드에서 movies.map을 하면 

movie(current element of the cycle)에 movies의 객체가 하나씩 들어가고 

화살표 다음 내용을 리턴한다. 

위 코드로 보면 movie에 movies[0]이 movies[1], movies[2], movies[3]이 순서대로 

들어간다는 것이다.

1.4. Validating Props with prop-type

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import './Movie.css';

class Movie extends Component {

  static propTypes = {
    title: PropTypes.string.isRequired,
    poster: PropTypes.string,
  }

  render() {
    return(
      <div>
        <MoviePoster poster={this.props.poster}/>
        <h1>{this.props.title}</h1>
      </div>
    )
  }
}

class MoviePoster extends Component {
  render() {
    return(
      <img src={this.props.poster}/>
    )
  }
}

export default Movie;


위의 내용처럼 static propTypes라는 객체를 통해서 부모 컴포넌트에서 얻는 

데이터의 타입, 존재 유무, 필수 유무 등을 확인 할 수 있다. 

해당 데이터가 조건을 충족하지 못 할 경우 에러 메시지가 콘솔에 출력 된다.

validation시 유용하게 쓸 수 있다.

You May Also Like

0 comments