본문 바로가기

개발새발 개발자/ReactJS

[ReactJS] 5-1. Smart vs Dumb Components

모든 컴포넌트가 state가 있는 것은 아니다. stateless functional component도 존재한다. state가 없고 필요하지도 않기 때문에 dumb component 라고 한다. 반대로 state가 있는 컴포넌트는 smart component라고 부른다.


1
2
3
4
5
6
7
_renderMovies = () => {
    const movies = this.state.movies.map((movie, index) => {
      // 괄호 넣는 것 잊지 말기
      return <Movie title={movie.title} poster={movie.poster} key={index} /> //key prop으로 index를 작성
    })
    return movies
  }
cs

state가 없고 props밖에 없을 때는 위처럼 클래스 컴포넌트를 쓰는 대신에 그들을 functional 컴포넌트로 바꾼다.


1. functional component


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
import React, { Component } from "react"
import PropTypes from "prop-types"
import "./Movie.css"
 
class Movie extends Component {
  static propTypes = {
    title: PropTypes.string,
    poster: PropTypes.string
    // title과 poster는 string이라는 뜻이 됨
  }
 
  render() {
    // component엔 렌더
 
    // props
    //console.log(this.props);
    return (
      <div>
        {/* 큰 컴포넌트 안에 작은 컴포넌트를 넣는 방식으로 작업 */}
        <MoviePoster poster={this.props.poster} />
        <h1>{this.props.title}</h1>
      </div>
    ) // return 꼭 써주기
  }
}
 
class MoviePoster extends Component {
  static propTypes = {
    poster: PropTypes.string.isRequired
  }
 
  render() {
    console.log(this.props)
    return <img src={this.props.poster} alt="Movie Poster" />
  }
}
 
 
export default Movie //App.js로 내보냄
 
cs

state가 있을 때의 Movie.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
import React, { Component } from "react"
import PropTypes from "prop-types"
import "./Movie.css"
 
class Movie extends Component {
  static propTypes = {
    title: PropTypes.string,
    poster: PropTypes.string
    // title과 poster는 string이라는 뜻이 됨
  }
 
  render() {
    // component엔 렌더
 
    // props
    //console.log(this.props);
    return (
      <div>
        {/* 큰 컴포넌트 안에 작은 컴포넌트를 넣는 방식으로 작업 */}
        <MoviePoster poster={this.props.poster} />
        <h1>{this.props.title}</h1>
      </div>
    ) // return 꼭 써주기
  }
}
 
function MoviePoster({ poster }) {
  return <img src={this.props.poster} alt="Movie Poster" />
}
 
export default Movie //App.js로 내보냄
cs

state가 없을 때의 Movie.js


위와 아래의 코드는 같은 의미다. 둘 다 img와 props를 return한다.


1
2
3
function MoviePoster({ poster }) {
  return <img src={poster} alt="Movie Poster" />
}
cs

두 번째 컴포넌트, 즉 functional component는 클래스가 아니기 때문에 props를 지우고 poster만 남긴다.


왜 dump/smart 컴포넌트를 구분할까? 어떤 컴포넌트는 그냥 return 하기 위해 존재한다. 이 컴포넌트는 componentWillMount, function, updateState...다 필요 없다. 원래의 코드를 보면 1개의 props만 있고 1개의 html 태그만 필요하다. 그래서 두번째처럼 간단하게 functional 컴포넌트를 만드는 것이다. 내가 기억해야 할 규칙은, 이들은 state가 없다는 거다. function render나 life cycle도 없다. 갖고있는 것은 오직 return 뿐이다.


실행해보면 이전과 같이 loading -> 5초 -> 무비 리스트가 뜬다. 오류는 없다. 그냥 functional component를 사용할 뿐.


2. Prop.Types를 확인하는 법


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
import React, { Component } from "react"
import PropTypes from "prop-types"
import "./Movie.css"
 
class Movie extends Component {
  static propTypes = {
    title: PropTypes.string,
    poster: PropTypes.string
    // title과 poster는 string이라는 뜻이 됨
  }
 
  render() {
    // component엔 렌더
 
    // props
    //console.log(this.props);
    return (
      <div>
        {/* 큰 컴포넌트 안에 작은 컴포넌트를 넣는 방식으로 작업 */}
        <MoviePoster poster={this.props.poster} />
        <h1>{this.props.title}</h1>
      </div>
    ) // return 꼭 써주기
  }
}
 
function MoviePoster({ poster }) {
  return <img src={poster} alt="Movie Poster" />
}
 
MoviePoster.propTypes = {
  poster: PropTypes.string.isRequired
}
 
export default Movie //App.js로 내보냄
 
cs

이렇게 입력하고 페이지를 실행했을 때


콘솔이 클린하면 string.


만약 poster: PropTypes.string.isRequired 를 number로 변경하면 오류가 난다.


3. movie 컴포넌트를 functional로 변경하기


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import React, { Component } from "react"
import PropTypes from "prop-types"
import "./Movie.css"
 
class Movie extends Component {
  static propTypes = {
    title: PropTypes.string,
    poster: PropTypes.string
  }
 
  render() {
    return (
      <div>
        <MoviePoster poster={this.props.poster} />
        <h1>{this.props.title}</h1>
      </div>
    ) // return 꼭 써주기
  }
}
cs
원래 Movie.js 코드


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import React from "react"
import PropTypes from "prop-types"
import "./Movie.css"
 
function Movie({ title, poster }) {
  return (
    <div>
      <MoviePoster poster={poster} />
      <h1>{title}</h1>
    </div>
  )
}
 
function MoviePoster({ poster }) {
  return <img src={poster} alt="Movie Poster" />
}
 
MoviePoster.propTypes = {
  poster: PropTypes.number.isRequired
}
 
export default Movie //App.js로 내보냄
 
cs

funtional component로 변경하면서 render 하던 return의 모든 내용을 function 안으로 집어넣고 나머지는 지운다. import에 있는 component도 지운다. 더이상 컴포넌트는 사용하지 않으니까. 클래스가 아니므로 this.props도 꼭 삭제해준다. 클래스는 그 안에 this라는 키워드가 있다. 하지만 이건 functional 컴포넌트라서 this가 필요없다. 이미 props를 쓰니까.


functional/dump 컴포넌트를 가지고 있으면 render function, willmount, didmount...다 필요없다. html을 return할 뿐이다. 하지만 state를 잃게 된다. 업데이트 하는 등등 그런 멋진 기능들이 사라진다. 무비 포스터같은 컴포넌트에는 사용해도 무방하다.