만들면서 배우는 리액트 튜토리얼 - 8.어플리케이션 완성(HTML과 CSS 처리)
1.1. HTML 파트
import React, { Component } from 'react';
import './App.css';
import Movie from './Movie'
class App extends Component {
state = [
]
_renderMovies = () => {
const movies = this.state.movies.map(movie => {
return <Movie
title={movie.title_english}
poster={movie.medium_cover_image}
genres={movie.genres}
synopsis={movie.synopsis}
key={movie.id}
/>
})
return movies
}
componentDidMount() {
this._getMovies();
}
_getMovies = async () => {
const movies = await this._callApi()
this.setState({
movies // ES5 movies: movies
})
}
_callApi = () => {
return fetch('https://yts.am/api/v2/list_movies.json?sort_by=rating')
.then(potato => potato.json())
.then(json => json.data.movies)
.catch(err => console.log(err))
}
render() {
return (
<div className="App">
{this.state.movies ? this._renderMovies() : "Loading..."}
</div>
);
}
}
export default App;
App.js
import React from 'react';
import PropTypes from 'prop-types';
import LinesEllipsis from 'react-lines-ellipsis';
import './Movie.css';
function Movie({title, poster, genres, synopsis}) {
return (
<div className="Movie">
<div className="Movie__Column">
<MoviePoster poster={poster} alt={title}/>
</div>
<div className="Movie__Column">
<h1>{title}</h1>
<div className="Movie__Genres">
{genres.map((genre, index) => <MovieGenre genre={genre} key={index}/>)}
</div>
<p className="Movie__Synopsis">
<LinesEllipsis
text={synopsis}
maxLine='3'
ellipsis=' ...'
trimRight
basedOn='letters'
/>
</p>
</div>
</div>
)
}
function MoviePoster({poster, alt}) {
return (
<img src={poster} className="Movie__Poster" alt={alt} title={alt}/>
)
}
function MovieGenre({genre}) {
return (
<span className="Movie__Genre">{genre}</span>
)
}
Movie.propTypes = {
title: PropTypes.string.isRequired,
poster: PropTypes.string.isRequired,
genres: PropTypes.array.isRequired,
synopsis: PropTypes.string.isRequired,
}
MoviePoster.propTypes = {
poster: PropTypes.string.isRequired,
alt: PropTypes.string.isRequired,
}
MovieGenre.propTypes = {
genre: PropTypes.string.isRequired,
}
export default Movie;
Movie.js
App.js에서 genre, synopsis 등의 다른 prop들을 추가했다.
prop이 추가 됐으니 타입 검증을 위한 propType도 추가되었고
장르는 여러 개일 수 있기 때문에 array로 검증했다.
그리고
해당 prop들을 화면에 출력하기 위해 기본적인 HTML(div, h1, p)과 React 문법
(className 등)을
이용하여 Movie.js에 Movie 함수를 업데이트했다.
화면은
Movie__Columns라는 이름으로 크게 포스터와 포스터 내용으로 구성했고
두번째 Movie__Columns 안에 Genre를 나타내는 Movie__Genre, 줄거리를 나타내는
Movie__Synopsis가 들어가도록 구성했다.
특히
Genre부분은 더 세련된 코드를 위해 MovieGenre라는 이름의 function 컴포넌트로
나누고 이를 사용했다.
1.2. CSS파트
.App {
padding: 50px;
display: flex;
justify-content: space-around;
flex-wrap: wrap;
height: 100%;
}
.App--loading{
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
App.css
.Movie{
background-color: white;
width: 40%;
display: flex;
justify-content: space-between;
align-items: flex-start;
flex-wrap: wrap;
margin-bottom: 50px;
text-overflow: ellipsis;
padding: 0 20px;
box-shadow: 0 8px 38px rgba(133, 133, 133, 0.3), 0 5px 12px rgba(133, 133, 133, 0.22);
}
.Movie__Column{
width: 30%;
box-sizing: border-box;
text-overflow: ellipsis;
}
.Movie__Column:last-child {
padding: 20px 0;
width: 60%;
}
.Movie h1{
font-size: 20px;
font-weight: 600;
}
.Movie .Movie__Genres{
display: flex;
flex-wrap: wrap;
margin-bottom: 20px;
}
.Movie__Genres .Movie__Genre {
margin-right: 10px;
color: #B4B5BD;
}
.Movie .Movie__Synpsis {
text-overflow: ellipsis;
color: #B4B5BD;
overflow: hidden;
}
.Movie .Movie__Poster{
max-width: 100%;
position: relative;
top: -20px;
box-shadow: -10px 19px 38px rgba(83, 83, 83, 0.3), 10px 15px 12px rgba(80, 80, 80, 0.22);
}
@media screen and (min-width:320px) and (max-width:667px) {
.Movie {
width:100%;
}
}
@media screen and (min-width:320px) and (max-width:667px) and (orientation: portrait) {
.Movie {
width:100%;
flex-direction: column;
}
.Movie__Poster {
top: 0;
left:0;
width:100%;
}
.Movie__Column {
width: 100% !important;
}
}
Movie.css
body {
margin: 0;
padding: 0;
font-family: sans-serif;
background-color: #EFF3F7;
height: 100%;
}
html, #root {
height: 100%;
}
Index.css
[완성된 모습] |
[포스터를 누르면 사이트로 연결되는 모습] |
그림의 좌우 라인을 맞출 때 사용하는 justify-content
그림의 위아래 라인을 맞출 때 사용하는 align-items
0 comments