Powered by Blogger.
  • Home
  • About
  • Contact
facebook instagram pinterest Email

chuckolet's Blog

Musician & Developer

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


Share
Tweet
Pin
Share
No comments
Older Posts

About Me

Unknown
View my complete profile

Categories

  • Android (4)
  • AWS (1)
  • Coding Test (3)
  • Computer (5)
  • etc (1)
  • Git (2)
  • JAVA (3)
  • Linux (6)
  • Machine Learning (7)
  • Music (1)
  • PHP (1)
  • Python (8)
  • React Native (1)
  • SQL (1)
  • Web (12)
  • XML (2)
  • 주식 (1)

Popular Posts

  • 아나콘다 파이썬에서 IDLE 실행하기
  • Solution: CUDA 9.0 설치 실패 오류 (CUDA 9.0 installer failed on windows 10)
  • 에어드로이드(Airdroid) 로컬 연결 모드 접속 방법(원격 연결 모드로만 접속 해결)
  • 우분투 16.04 크롬 설치, 블루 스크린 문제
  • 마우스 오른쪽 클릭으로 CMD 열기 (How do I right click command prompt?)

recent posts

Total Pageviews

Follow Me

  • facebook
  • instagram
  • Google+
  • youtube

Created with by ThemeXpose