-
React Container and Presenter PatternProject using React/Cloning Netflix 2021. 5. 9. 05:26
개요
React app을 어떻게 만들것인지에 대한 디자인 패턴이다. 하나의 파일 안에 데이터를 처리하는 비지니스 로직과
Container
어떻게 동작하는지와 비지니스 로직과 관련된 코드가 있다. api를 수행하고 state를 조작해서 Presenter에게 넘겨준다.
Presenter
사용자가 직접 보고, 조작하는 컴포넌트다. Container가 넘겨준 props를 가지고 html을 구성한다. state 조작은 Container가 다 하기 때문에 Presenter는 state를 조작하지 않는다.
Movie
Movie Directory
Movie page의 directory 구조다. Container와 Presenter 디자인 패턴을 설명하기 위해 완성 본을 가져왔다.
index.js
import MovieContainer from "./MovieContainer"; export default MovieContainer;
MovieContainer
import { moviesApi } from "api"; import React from "react"; import MoviePresenter from "./MoviePresenter"; export default class extends React.Component { state = { loading: true, nowPlaying: null, upcoming: null, popular: null, error: null, }; async componentDidMount() { try { const { data: { results: nowPlaying }, } = await moviesApi.nowPlaying(); const { data: { results: upcoming }, } = await moviesApi.upcoming(); const { data: { results: popular }, } = await moviesApi.popular(); this.setState({ nowPlaying, upcoming, popular, }); } catch { this.setState({ error: "Can't find movie information.", }); } finally { this.setState({ loading: false, }); } } render() { const { nowPlaying, upcoming, popular, error, loading } = this.state; return ( <MoviePresenter nowPlaying={nowPlaying} upcoming={upcoming} popular={popular} error={error} loading={loading} /> ); } }
state와 componentDidMount()를 이용해서 state를 조작하고 그 값을 MoviePresenter에게 전달하기만 했다.
MoviePresenter
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: 10px; `; const MoviePresenter = ({ nowPlaying, upcoming, popular, error, loading }) => ( <> <Helmet> <title>Movies | Nomflix</title> </Helmet> {loading ? ( <Loader /> ) : ( <Container> <Section title="Now Playing"> {nowPlaying.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> <Section title="Upcoming"> {upcoming.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> <Section title="Popular"> {popular.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> </Container> )} </> ); MoviePresenter.propTypes = { nowPlaying: PropTypes.array, popular: PropTypes.array, upcoming: PropTypes.array, loading: PropTypes.bool.isRequired, error: PropTypes.string, }; export default MoviePresenter;
MoviePresenter는 MovieContainer로부터 props를 받아와서 UI만을 구성한다.
참고 자료
- 노마드 코더의 React 멤버쉽 강의
- 기억보다 기록을
소스 코드
github.com/zpskek/Nomflix-v2/commit/7d0d4a233cae36e527ed3e27ba432d8dda95aa7e
'Project using React > Cloning Netflix' 카테고리의 다른 글
React GlobalStyles.js (0) 2021.05.09 React api.js (0) 2021.05.09 React Router 설정 with react-router-dom (0) 2021.05.02 Cloning Netflix settup (0) 2021.05.02 What is React? (0) 2021.05.02