만들면서 배우는 리액트 튜토리얼 - 3.Props
리액트의 주요 컨셉으로 크게 Prop과 State가 있는데
오늘 배울 것은 이 중 하나인 Prop이다.
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시 유용하게 쓸 수 있다.
0 comments