1. App.css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | .App { padding: 50px; display: flex; justify-content: space-around; flex-wrap: wrap; font-size: 14px; } .App--loading { display: flex; justify-content: center; align-items: center; height: 100%; } | cs |
2. App.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | import React, { Component } from "react" import "./App.css" import Movie from "./Movie" //Movie.js에서 여기로 export한 컴포넌트를 import class App extends Component { state = {} // 삭제하면 'movies' property를 읽을 수 없음 componentDidMount() { this._getMovies() } // 함수를 만들어 놓고 _renderMovies = () => { const movies = this.state.movies.map((movie, index) => { console.log(movie) // 괄호 넣는 것 잊지 말기 return ( <Movie title={movie.title_english} poster={movie.medium_cover_image} key={movie.id} genres={movie.genres} synopsis={movie.synopsis} /> ) //key prop으로 index를 작성 }) return movies } _getMovies = async () => { const movies = await this._callApi() this.setState({ movies }) } _callApi = () => { return ( fetch("https://yts.am/api/v2/list_movies.json?sort_by=download_count?sort_by=rating") // 위의 라인이 완료되면 뭔가를 해라 .then(potato => potato.json()) .then(json => json.data.movies) // 근데 그 라인이 에러가 있으면 catch해서 나한테 보여줘라 .catch(err => console.log(err)) ) } // render에 조건문으로 집어넣기 render() { const { movies } = this.state return ( <div className={movies ? "App" : "App--Loading"}> {movies ? this._renderMovies() : "Loading" // 데이터가 없다면 'Loading'을 띄우고, 있으면 영화정보가 보이도록 한다. } </div> ) } } export default App | cs |
const { movies } = this.state는 <div className={this.state.movies ? "App" : "App--Loading"}> 와 같다.
state에 movies가 있는지 물어보고, 있으면 div 이름을 app으로, 없으면 app--loading으로 하도록 설정했다.
3. index.css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | body { margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; background-color: #eff3f7; height: 100%; } html, #root { height: 100%; } | cs |
4. Movie.css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | .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__Synopsis { 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; } } | cs |
그림자 등등 설정해주고, 마지막엔 responsive 작업
5. Movie.js에 lines-ellipsis 설치 및 추가
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | 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__Columns"> <MoviePoster poster={poster} alt={title} /> </div> <div className="Movie_Columns"> <h1>{title}</h1> <div className="Movie__Genres"> {genres && genres.map((genre, index) => <MovieGenre genre={genre} key={index} />)} </div> <p className="Movie__Synopsis"> {synopsis} <LinesEllipsis text={synopsis} maxLine="3" ellipsis="..." trimRight basedOn="letters" /> </p> </div> </div> ) } function MoviePoster({ poster, alt }) { return <img src={poster} alt={alt} title={alt} className="Movie__Poster" /> } function MovieGenre({ genre }) { return <span className="Movie__Genre">{genre}</span> } // prop의 타입 확인하기 Movie.propTypes = { title: PropTypes.string.isRequired, poster: PropTypes.string.isRequired, genres: PropTypes.arrayOf(PropTypes.string), synopsis: PropTypes.string.isRequired } MoviePoster.propTypes = { poster: PropTypes.string.isRequired, alt: PropTypes.string.isRequired } MovieGenre.propTypes = { genre: PropTypes.string.isRequired } export default Movie //App.js로 내보냄 | cs |
yarn add react-lines-ellipsis
먼저 lines-ellipsis를 터미널에서 설치 후, import 하고 코드를 넣어주면 긴 시놉시스 전체를 출력하지 않고 줄여서 표시된다.
'개발새발 개발자 > ReactJS' 카테고리의 다른 글
[ReactJS] 8-1. Building for production (0) | 2018.10.04 |
---|---|
[ReactJS] 7-1. Updating Movie Component (0) | 2018.10.02 |
[ReactJS] 6-3. Async, Await in React (2) | 2018.10.02 |
[ReactJS] 6-2. Promises (0) | 2018.10.01 |
[ReactJS] 6-1. Ajax in React (0) | 2018.10.01 |