Front-End/React

[React] 카운터 구현하기 - 프레젠테이셔널, 컨테이너 컴포넌트

LightSource 2022. 9. 21. 16:31

이글은 이전 글인 [React] 리덕스 - counter와 todos 모듈 만들고 합치기 와 이어집니다.

 

[React] 리덕스 - counter와 todos 모듈 만들고 합치기

이 글은 velopert님의 벨로퍼트와 함께하는 모던 리액트를 공부하며 쓴 글입니다. https://react.vlpt.us/ 벨로퍼트와 함께하는 모던 리액트 · GitBook 벨로퍼트와 함께하는 모던 리액트 본 강의자료는 패

scoring.tistory.com

 

프리젠테이셔널 컴포넌트 만들기

프리젠테이셔널 컴포넌트란?

  • 리덕스 스토어에 직접적으로 접근하지않고, 필요한 값 또는 함수를 props 로만 받아와서 사용하는 컴포넌트
  • 주로 UI를 선언하는 것에 집중하며, 필요한 값이나 함수는 props로 받아와서 사용하는 형태로 구현

프리젠테이셔널 컴포넌트의 특징

  • 직접적으로 보여지는 부분에 대해 담당
  • store에 의존적이지 않다.
  • props를 통해 데이터와 callback을 전달 받는다.
  • 마크업과 스타일을 가진다.
  • 데이터를 직접적으로 변경하지 않는다.
  • UI 상태값 이외에 대체로 다른 상태값을 가지고 있지 않는다.

컴포넌트 생성

Counter.js

import React from 'react';

function Counter({ number, diff, onIncrease, onDecrease, onSetDiff }) {
  const onChange = e => {
    // e.target.value 의 타입은 문자열이기 때문에 숫자로 변환해주어야 합니다.
    onSetDiff(parseInt(e.target.value, 10));
  };
  return (
    <div>
      <h1>{number}</h1>
      <div>
        <input type="number" value={diff} min="1" onChange={onChange} />
        <button onClick={onIncrease}>+</button>
        <button onClick={onDecrease}>-</button>
      </div>
    </div>
  );
}

export default Counter;

컨테이너 컴포넌트 만들기

컨테이너 컴포넌트란?

  • 리덕스 스토어의 상태를 조회하거나, 액션을 디스패치 할 수 있는 컴포넌트
  • HTML 태그들을 사용하지 않고, 다른 프리젠테이셔널 컴포넌트를 불러와서 사용

컨테이너 컴포넌트의 특징

  • 데이터 핸들링에 대한 위주로 개발
  • 마크업이나 스타일을 가지지 않는다.
  • 리덕스의 액션이나 상태 변경에 대한 로직을 담고, 프레젠테이셔널 컴포넌트에 해당 상태를 전달하거나 함수를 제공
  • 다른 프레젠테이셔널 컴포넌트나 컨테이너 컴포넌트를 관리

컴포넌트 생성

CounterContainer.js

import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import Counter from '../components/Counter';
import { increase, decrease, setDiff } from '../modules/counter';

function CounterContainer() {
  // useSelector는 리덕스 스토어의 상태를 조회하는 Hook입니다.
  // state의 값은 store.getState() 함수를 호출했을 때 나타나는 결과물과 동일합니다.
  const { number, diff } = useSelector(state => ({
    number: state.counter.number,
    diff: state.counter.diff
  }));

  // useDispatch 는 리덕스 스토어의 dispatch 를 함수에서 사용 할 수 있게 해주는 Hook 입니다.
  const dispatch = useDispatch();
  // 각 액션들을 디스패치하는 함수들을 만드세요
  const onIncrease = () => dispatch(increase());
  const onDecrease = () => dispatch(decrease());
  const onSetDiff = diff => dispatch(setDiff(diff));

  return (
    <Counter
      // 상태와
      number={number}
      diff={diff}
      // 액션을 디스패치 하는 함수들을 props로 넣어줍니다.
      onIncrease={onIncrease}
      onDecrease={onDecrease}
      onSetDiff={onSetDiff}
    />
  );
}

export default CounterContainer;

렌더링

  • App컴포넌트에서 렌더링

App.js

import React from 'react';
import CounterContainer from './containers/CounterContainer';

function App() {
  return (
    <div>
      <CounterContainer />
    </div>
  );
}

export default App;

컴포넌트를 컨테이너와 프레젠테이셔널로 나누는 이유

  • UI와 DATA핸들링 부분을 분리함으로써 재사용성을 높여주기 위함이다.

정리

프레젠테이션 컴포넌트

  • 보여지는 부분에 대해 담당
  • store 의존 x
  • props를 통해 데이터를 전달받음
  • 데이터를 직접적으로 변경x

컨테이너 컴포넌트

  • 데이터 핸들링에 대해 담당
  • 리덕스의 액션이나 상태변경 로직을 담고, 프레젠테이셔널 컴포넌트에 상태와 함수를 전달
  • 다른 프레젠테이셔널 컴포넌트나 컨테이너 컴포넌트를 관리

컴포넌트를 분리한 이유

  • UI와 DATA핸들링 부분을 분리함으로써 재사용성을 높여주기 위함이다.

참고

이 글은 velopert님의 벨로퍼트와 함께하는 모던 리액트를 공부하며 쓴 글입니다.

https://react.vlpt.us/

 

벨로퍼트와 함께하는 모던 리액트 · GitBook

벨로퍼트와 함께하는 모던 리액트 본 강의자료는 패스트캠퍼스 온라인 강의에서 제공하는 리액트 강의에서 사용되는 강의 문서입니다. 이 튜토리얼은 여러분들이 JavaScript 의 기초를 잘 알고있

react.vlpt.us

 

반응형