-
React - Search Container and PresenterProject using React/Cloning Netflix 2021. 5. 9. 11:07
Search/SearchContainer.js
import { moviesApi, tvApi } from "api"; import React from "react"; import SearchPresenter from "./SearchPresenter"; export default class extends React.Component { state = { movieResults: null, tvResults: null, searchTerm: "", loading: false, error: null, }; handleSubmit = (event) => { event.preventDefault(); const { searchTerm } = this.state; if (searchTerm !== "") { this.searchByTerm(); } }; updateTerm = (event) => { const { target: { value }, } = event; this.setState({ searchTerm: value, }); }; searchByTerm = async () => { const { searchTerm } = this.state; this.setState({ loading: true }); try { const { data: { results: movieResults }, } = await moviesApi.search(searchTerm); const { data: { results: tvResults }, } = await tvApi.search(searchTerm); this.setState({ movieResults, tvResults, }); } catch { this.setState({ error: "Can't find results." }); } finally { this.setState({ loading: false }); } }; render() { const { movieResults, tvResults, searchTerm, loading, error } = this.state; return ( <SearchPresenter movieResults={movieResults} tvResults={tvResults} loading={loading} error={error} searchTerm={searchTerm} handleSubmit={this.handleSubmit} updateTerm={this.updateTerm} /> ); } }
updateTerm
prop으로 넘겨준 state는 변경이 Read만 가능하다. 변경할 수 있는 방법은 this.setState를 이용한 방법 뿐이다. input에서 updateTerm으로 원하는 키워드를 쓴다.
searchByTerm
state에서 searchByTerm을 가져와서 movieResults와 tvResults 값을 가져온다.
Search/Searchresenter.js
import Helmet from "react-helmet"; import styled from "styled-components"; import PropTypes from "prop-types"; import Loader from "Components/Loader"; import Poster from "Components/Poster"; import Section from "Components/Section"; const Container = styled.div` padding: 20px; `; const Form = styled.form` margin-bottom: 50px; `; const Input = styled.input` all: unset; font-size: 20px; width: 100%; `; const SearchPresenter = ({ movieResults, tvResults, loading, searchTerm, handleSubmit, updateTerm, error, }) => ( <Container> <Helmet> <title>Search | Nomflix</title> </Helmet> <Form onSubmit={handleSubmit}> <Input placeholder="Search Movies or TV Shows..." value={searchTerm} onChange={updateTerm} /> </Form> {loading ? ( <Loader /> ) : ( <> {movieResults && movieResults.length > 0 && ( <Section title="Movie Results"> {movieResults.map((movie) => ( <Poster key={movie.id} id={movie.id} imageUrl={movie.poster_path} title={movie.original_title} rating={movie.vote_average} year={movie.release_date?.substring(0, 4)} isMovie={true} /> ))} </Section> )} {tvResults && tvResults.length > 0 && ( <Section title="TV Show Results"> {tvResults.map((tv) => ( <Poster key={tv.id} id={tv.id} imageUrl={tv.poster_path} title={tv.original_name} rating={tv.vote_average} year={tv.first_air_date?.substring(0, 4)} /> ))} </Section> )} </> )} </Container> ); SearchPresenter.propTypes = { movieResults: PropTypes.array, tvResults: PropTypes.array, error: PropTypes.string, searchTerm: PropTypes.string, loading: PropTypes.bool.isRequired, handleSubmit: PropTypes.func.isRequired, updateTerm: PropTypes.func.isRequired, }; export default SearchPresenter;
key
nowPlaying, upcoming, popular는 모두 배열이다. 이들을 map을 이용해서 <Poster>를 부르고 있다. 이 때 리스트 안에 있는 <Poster>에 key 값을 추가해야만 한다.
prop-types
설치
$ npm i prop-types
개요
prop-types는 prop의 type을 정의한다. prop을 받을 component 뒤에 method 형식으로 propTypes를 하고 객체를 정의한다.
위 코드와 같이 type을 정의하면 MoviePresenter가 받아들이는 prop이 옳지 않은 type일 때 error를 일으켜 개발자가 실수 하는 것을 막아준다. 만약 React를 typescript로 짰다면 prop-types는 필요가 없다.
참고 자료
- 노마드 코더의 React 멤버쉽 강의
- prop-types
- React propTypes 설명
- Children prop
소스 코드
github.com/zpskek/Nomflix-v2/commit/6a98d6b6d1a1ea14b2618ea0d9e0ba2abb35fdfa
'Project using React > Cloning Netflix' 카테고리의 다른 글
Netlify에 React 배포 (0) 2021.05.09 React - Create Detail Container and Presenter (0) 2021.05.09 React - Create TV Container and Presenter (0) 2021.05.09 React - Create MoviePresenter (0) 2021.05.09 React - Create Loader.js (0) 2021.05.09