react "container and presentational component patterns"

May 30th 2020 by jyoon

소개

  • 어플리케이션이 커질수록 컴포넌트도 복잡해지고 이에 따라 데이터와 state를 관리하는것도 복잡해진다.
  • 코드 관리도 어려워지고 가독성도 떨어진다.
  • 그래서 "container and presentational component patterns"라는 패턴을 도입하면 관리하기 수월해진다.

container pattern이란?

  • continaer components 인스턴스는 redux library의 connect()Relay library의 createContainer(The production-ready GraphQl client for React.) 같은 higher order components에 의해서 생성된다.
  • 이 container pattenr이 적용된 컴포넌트는 다른 어플리케이션에서 재사용 될 수 있다.
  • presentaionnal component가 어떻게 동작하는지 보내줄 데이터를 fetching 하고 전달한다. 즉 data를 관리하는코드가 있다.
  • presentational component를 포함한다. 반대로 presentational component은 container를 포함하지 않는다.

presentational pattern이란?

  • 화면에 보여지는 코드가 모여 있다.
  • 대부분의 경우 render 함수 이외에는 있지 않다.
  • 데이터를를 호출하고 가공하는 역할이 아니다.
  • 거의 state를 바꾸는 일이 없다.
  • 가장 좋은 패턴은 state가 없는 component다.
  • 다른 component에서 presentation영역으로 사용 될 수 있다.

container, presentational 파일 구조

데이터 정보를 다루는 파일 container.js가 화면을 다루는 파일 presenter.js를 데이터를 넘겨주면서 호출하는 구조를 가진다.

container.js
  ㄴ presenter.js

예시

  • container and presentational component patterns이 적용된 코드
  class CarList extends React.Component {
    this.state = { cars: [] };

    componentDidMount() {
      getCars(cars =>
        this.setState({ cars: cars }));
    }
    render() {
      return (
        <ul>
          {this.state.cars.map(e => (
            <li>{e.make}: {e.model}</li>
          ))}
        </ul>
      );
    }
  }

위 예제를 패턴 적용한 두 코드

  • container component pattern code

    • server와 통신하는 fetching하는 로직와 presenter component(CarsList)를 호출해 data를 전달하고 있다.
class CarListContainer extends React.Component {
  state = { cars: [] }
  componentDidMount() {
    //fetching data
    getCars(cars => this.setState({ cars: cars }))
  }
  render() {
    return <CarsList cars={this.state.cars} />
  }
}
  • presentational component pattern

    • CarsList 컴포넌트가 cars라는 prop를 전달 받는다.
const CarsList = props => (
  <ul>
    {props.cars.map(e => (
      <li>
        {e.make}: {e.model}
      </li>
    ))}
  </ul>
)

참고