React 일회용 앱 2: 영화 검색 앱
규칙(상기시키기 위해)
앱 2 - 영화 검색 앱
다음은 여러분이 빌드하기를 기대하는 스크린샷입니다.
이 앱은 다음 방법을 이해하고 있음을 보여줍니다.
당신의 시간이 지금 시작됩니다! 작업을 완료할 때까지 내 솔루션을 보지 마십시오.
내 솔루션
OMDb API을 사용하여 동영상 데이터를 가져왔습니다. API 키를 받아야 합니다(무료입니다). PostMan에서 다양한 요청을 가지고 놀면서 API에 익숙해져야 했기 때문에 이 작업을 완료하는 데 60분 이상을 보냈다고 고백해야 합니다. 항상 그렇듯이 저는 create-react-app을 사용하여 프로젝트를 생성했습니다.
내 앱을 구성하려면 컨테이너와 구성 요소를 결정해야 했습니다.
내 폴더 구조는 다음과 같습니다.
MovieCard.js:
이 구성 요소는 선택한 동영상을 표시하는 데 사용됩니다. 소품을 통해 동영상 데이터를 받습니다.
import React from 'react';
import './MovieCard.css';
const MovieCard = (props) => {
return (
<div className="container">
<div className="movie-card">
<div className="movie-header" style={{ backgroundImage: `url(${props.movie.Poster})` }}>
</div>
<div className="movie-content">
<div className="movie-content-header">
<h3 className="movie-title">{props.movie.Title}</h3>
</div>
<div className="movie-info">
<div className="info-section">
<label>Released</label>
<span>{props.movie.Released}</span>
</div>
<div className="info-section">
<label>IMDB Rating</label>
<span>{props.movie.imdbRating}</span>
</div>
<div className="info-section">
<label>Rated</label>
<span>{props.movie.Rated}</span>
</div>
<div className="info-section">
<label>Runtime</label>
<span>{props.movie.Runtime}</span>
</div>
</div>
<div className="plot" style={{fontSize: '12px'}}>
<p>{props.movie.Plot}</p>
</div>
</div>
</div>
</div>
);
};
export default MovieCard;
MovieCard.css:
.container {
display: flex;
flex-wrap: wrap;
max-width: 100%;
margin-left: auto;
margin-right: auto;
justify-content: center;
}
.movie-card {
background: #ffffff;
box-shadow: 0px 6px 18px rgba(0,0,0,.1);
width: 100%;
max-width: 290px;
margin: 2em;
border-radius: 10px;
display:inline-block;
z-index: 10;
}
.movie-header {
padding:0;
margin: 0;
height: 434px;
width: 100%;
display: block;
border-top-left-radius: 10px;
border-top-right-radius:10px;
background-size: cover;
}
.movie-content {
padding: 18px 18px 24px 18px;
margin: 0;
}
.movie-content-header, .movie-info {
display: table;
width: 100%;
}
.movie-title {
font-size: 24px;
margin: 0;
display: table-cell;
cursor: pointer;
}
.movie-title:hover {
color:rgb(228, 194, 42);
}
.movie-info {
margin-top: 1em;
}
.info-section {
display: table-cell;
text-transform: uppercase;
text-align:center;
}
.info-section:first-of-type {
text-align:left;
}
.info-section:last-of-type {
text-align:right;
}
.info-section label {
display: block;
color: rgba(0,0,0,.5);
margin-bottom: .5em;
font-size: 9px;
}
.info-section span {
font-weight: 700;
font-size: 11px;
}
@media only screen and (max-width: 400px) {
.movie-header {
height: 400px;
}
}
Search.js
다음으로 검색 입력과 반환된 결과 목록을 포함하는 검색 구성 요소가 있습니다.
다음은 Search.js입니다.
import React from 'react';
import './Search.css';
const Search = (props) => {
let resultList = null
if (props.searching && (props.defaultTitle !== '')) {
resultList = (
<ul className="results">
{props.results.map(item => (
<li key={item.imdbID} onClick={() => props.clicked(item)}>
<img src={item.Poster} alt="Movie Poster"/>
{item.Title}
</li>
))}
</ul>
)
}
return (
<div className="search">
<input type="search" name="movie-search" value={props.defaultTitle} onChange={props.search} />
{resultList}
</div>
);
};
export default Search;
검색.css
.search {
position: relative;
margin: 0 auto;
width: 300px;
margin-top: 10px;
}
.search input {
height: 26px;
width: 100%;
padding: 0 12px 0 25px;
background: white;
border: 1px solid #babdcc;
border-radius: 13px;
box-sizing: border-box;
box-shadow: inset 0 1px #e5e7ed, 0 1px 0 #fcfcfc;
}
.search input:focus {
outline: none;
border-color: #66b1ee;
box-shadow: 0 0 2px rgba(85, 168, 236, 0.9);
}
.search .results {
display: block;
position: absolute;
top: 35px;
left: 0;
right: 0;
z-index: 20;
padding: 0;
margin: 0;
border-width: 1px;
border-style: solid;
border-color: #cbcfe2 #c8cee7 #c4c7d7;
border-radius: 3px;
background-color: #fdfdfd;
}
.search .results li {
display: flex;
align-items: center;
padding: 5px;
border-bottom: 1px solid rgba(88, 85, 85, 0.3);
text-align: left;
height: 50px;
cursor: pointer;
}
.search .results li img {
width: 30px;
margin-right: 5px;
}
.search .results li:hover {
background: rgba(88, 85, 85, 0.1);
}
MovieSearch.js
모든 상태를 관리하고 소품을 통해 다른 구성 요소에 데이터를 전달하고 싶기 때문에 MovieSearch를 상태 저장 구성 요소로 만들었습니다. 먼저 omdb api에서 api 키를 얻었는지 확인하십시오.
내 MovieSearch.js 컨테이너는 다음과 같습니다.
import React, { Component } from 'react';
import axios from 'axios';
import MovieCard from '../../components/MovieCard/MovieCard';
import Search from '../../components/Search/Search';
class MovieSearch extends Component {
state = {
movieId: 'tt1442449', // default imdb id (Spartacus)
title: '',
movie: {},
searchResults: [],
isSearching: false,
}
componentDidMount() {
this.loadMovie()
}
componentDidUpdate(prevProps, prevState) {
if (prevState.movieId !== this.state.movieId) {
this.loadMovie()
}
}
loadMovie() {
axios.get(`http://www.omdbapi.com/?apikey=YOUR_API_KEY&i=${this.state.movieId}`)
.then(response => {
this.setState({ movie: response.data });
})
.catch(error => {
console.log('Opps!', error.message);
})
}
// we use a timeout to prevent the api request to fire immediately as we type
timeout = null;
searchMovie = (event) => {
this.setState({ title: event.target.value, isSearching: true })
clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
axios.get(`http://www.omdbapi.com/?apikey=YOUR_API_KEY&s=${this.state.title}`)
.then(response => {
if (response.data.Search) {
const movies = response.data.Search.slice(0, 5);
this.setState({ searchResults: movies });
}
})
.catch(error => {
console.log('Opps!', error.message);
})
}, 1000)
}
// event handler for a search result item that is clicked
itemClicked = (item) => {
this.setState(
{
movieId: item.imdbID,
isSearching: false,
title: item.Title,
}
)
}
render() {
return (
<div onClick={() => this.setState({ isSearching: false })}>
<Search
defaultTitle={this.state.title}
search={this.searchMovie}
results={this.state.searchResults}
clicked={this.itemClicked}
searching={this.state.isSearching} />
<MovieCard movie={this.state.movie} />
</div>
);
}
}
export default MovieSearch;
이 컨테이너는 상태를 처리하고 애플리케이션의 변경 사항을 업데이트하는 데 사용됩니다.
위의 코드는 단순히 초기 무비를 마운트할 때 로드합니다. movieId 상태를 검색하고 업데이트할 때마다 소품을 통해 MovieCard의 콘텐츠를 업데이트합니다.
결론
조금 급하게 만들었다고 생각할 수 있습니다. 이것은 튜토리얼이 아니라 React에서 생각할 수 있다고 느끼는 초보자를 위한 도전임을 기억하십시오. 내 코드는 단지 가이드일 뿐입니다. 읽어주셔서 감사하고 다음 편에서 뵙기를 바랍니다.
이건 버리지 않을 것 같아요 ;)
1부 링크:
Reference
이 문제에 관하여(React 일회용 앱 2: 영화 검색 앱), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/fleepgeek/react-throwaway-app-2-movie-search-app-3f3d텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)