본문 바로가기
WEB/기초

[WEB] React,Presentational Component vs Container Component (stateless,stateful), shallow ,deep copy

by IT황구 2021. 7. 15.
728x90
반응형

관심사 분리(separating concerns)를 위해서 React Component Pattern이란것이 존재합니다.

물론 공식적인 react의 용어는 아니지만, 개발자들이 만든 단어입니다.

https://levelup.gitconnected.com/react-component-patterns-ab1f09be2c82

 

React Component Patterns

Stateful x Stateless, Container x Presentational, HOCs, Render Callbacks and more

levelup.gitconnected.com

 

Presentational Component
Stateless component ( 항상 그런것은 아니다)

특징 :

1. 주로 view를 Rendering 하는것에 관심이 있습니다.

How things look (markup style등..)

2. props를 통해서 보내진 data를 기반으로 view를 rendering 합니다.

3. local state가 변경될 수 있습니다 (data가 아니고, UI의 생김새가 특정 값에 의해서 달라질 수 있다는 뜻입니다)

일반적으로 항상 일정한 layout과 값을 가지고 있기에, stateless라고도 불리지만 반드시 그런것은 아닙니다.

 

Container Component
stateful component

특징 :

1. Data fetching, state updates 처럼

어떤것이 작동되게 하는 역할을 가지고 있습니다

2. Presentational Component를 div로 감싸서 렌더링을 할 때 사용할 수 있습니다.

그렇다고 Container component가 View를 렌더링 했다고는 볼 수 없습니다. 이 컴포넌트의 role은 값 변경입니다.

감싸는 div같은것을 제외한 엘리먼트는 거의 존재하지 않습니다. 특히 style은 있을 수 없습니다.(container 니까요)

3. Presentational Component 에게 Data를 제공합니다. <PresenComp a = {DISHES} /> -> stateful 하다고 봅니다.

-> 값을 변경할 수 있지만, 항상 stateful은 아닙니다.

*속보

더이상 이걸 제안하신분도 2019년 이후로 이렇게 하는것을 장려하진 않는다네요.. 아 뭐야 그래도 알아둡시다. 이분도 기록으로 남겨둔답니다^^

강의가 2018년꺼라 그런지.. 이걸 못보셨나봐요

https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0

 

Presentational and Container Components

You’ll find your components much easier to reuse and reason about if you divide them into two categories.

medium.com

 

Container Component 예시

import { Navbar, NavbarBrand } from "reactstrap";
import Menu from "./MenuComponent";
import { useState } from "react";
import { DISHES } from "../shared/dishes";
import { DishDetail } from "./DishdetailComponent";
export function Main() {
  const [selectedDish, setDishSelect] = useState(null);
  //console.log(selectedDish);
  
  return (
    //Container Component div로 presentational component 감쌌음
    
    <div >
      <Navbar dark color="primary">
        <div className="container">
          <NavbarBrand href="/">Ristorint fuou fashion</NavbarBrand>
        </div>
      </Navbar>
      <div className="container">
      <Menu dish={DISHES} onClick={(dishID) => setDishSelect(dishID)}/>
      <DishDetail dish={DISHES.filter( (dish)=> dish.id === selectedDish)[0] } />
      </div>
    </div>
  );
}

설명 :

보시면 Menu, DishDetail같은 user-defined Component를 div로 감싸고 있습니다. 또한 parameter로 값을 보내주고 있지요?

나중에 보겠지만 functional Component라 hook을 사용했습니다.

Menu와 Dishdetail은 view의 역할을 하는 Presentational Component 입니다.

Presentational Component 예시 (Menu Component)

const Menu = (props) => {
  const menu = props.dish.map((dish) => {
    //react에서 아이템의 리스트를 만들떄는 key가 필요하다(각 아이템마다 키 필요)
    return (
      <div key={dish.id} className="col-xs-12 col-sm-12 col-md-5 col-lg-5 col-xl-5 m-1">
        <RenderDish dish={dish} onClick ={props.onClick}/>
      </div>
    );
  });
  // console.log("Menu Component render is invoked");

  return (
   
      <div className="row">{menu}</div>
    
  );
}

export default Menu;

이런식으로 Menu에 가면 View를 담당하는것이 렌더링되고 있습니다.

Shallow copy vs Deep copy

기억용으로 잠시 남깁니다.

1. Shallow Copy

두개의 변수 or 객체가 같은 reference object를 가리킵니다.

a = b; 로 한 후에

a를 변경시켰더니 b도 변경이 된다는 뜻입니다.

예시를 보면 js의 array는 shallow copy가 됩니다.

따라서 a.push(7)을 해서 a의 메모리주소에 7을 할당하니, shallow copy한 b도 같은 메모리를 바라보기에, 같이 복사가 된것입니다.

이것을 이해하지 못하고 썼으면, 왜 b에는 7이 들어가는지 알 수 없었을 것입니다

2. Deep copy

reference object 독립적입니다.

 

위에것처럼 하면 a와 b는 독립적인 값을 가집니다.

 

JSON.parse(JSON.stringify(arr))로 json형태로 복사하면 Deep-copy가 됩니다.

보시면 독립적이라서, 값을 추가하더라도 따로 추가되는것을 볼 수 있습니다.

감사합니다

728x90
반응형