Skip to content

Latest commit

 

History

History
215 lines (143 loc) · 4.95 KB

custom Hook으로 container 컴포넌트 대체.md

File metadata and controls

215 lines (143 loc) · 4.95 KB

custom Hook으로 container 컴포넌트 대체


container component

  • 전달한 state, dispatch 재사용 불가능
  • presentaion component 자체를 재사용 가능

container / presentation component를 사용하는 이유는 컴포넌트를 재사용하는 목적이 아니라, 단지 로직을 분리하기 위함의 목적이다.('관심을 분산시키기 위함')


custom hook

  • 반환하는 state와 dispatch 재사용 가능
  • presentaion component 자체에 custom hook이 있어 재사용 어려움

custom hook을 사용하는 이유는 컴포넌트안의 로직을 재사용하기 위한 목적이다.(물론 그안의 상태 로직을 분리할 수 있지만, 순수한 UI 컴포넌트를 재사용하기 어려움)


예제

container


redux module

import { createAction, handleActions } from "redux-actions";

// 액션 타입
const INCREASE_COUNT = "count/increase_count";
const DECREASE_COUNT = "count/decrease_count";

// 액션 생성함수

export const increase_count = createAction(INCREASE_COUNT);
export const decrease_count = createAction(DECREASE_COUNT);

// 초기값

const initialize = {
  count: 0,
};

// 리듀서

const count = handleActions(
  {
    [INCREASE_COUNT]: (state, action) => ({
      ...state,
      count: state.count + 1,
    }),
    [DECREASE_COUNT]: (state, action) => ({
      ...state,
      count: state.count === 0 ? 0 : state.count - 1,
    }),
  },
  initialize
);

export default count;

Container

import React from "react";
import { useDispatch, useSelector } from "react-redux";
import Count from "../../Count";
import { decrease_count, increase_count } from "../../modules/count";

function CountContainer(props) {
  const num = useSelector((state) => state.count.count);
  const dispatch = useDispatch();

  return <Count num={num} increase={increase} decrease={decrease} />;

  function increase() {
    dispatch(increase_count());
  }

  function decrease() {
    dispatch(decrease_count());
  }
}

export default CountContainer;

component

import React from "react";

function Count({ num, increase, decrease }) {
  return (
    <>
      <button onClick={increase}>increase</button>
      <button onClick={decrease}>decrease</button>
      <div>now count : {num}</div>
    </>
  );
}

export default Count;

위의 로직처럼 container 내부에서 dispatch와 state의 로직들을 store에서 가져와서 그대로 component에 props로 전달해준다.


container는 state에 대한 로직들을 관리하고

component는 오로지 UI를 관리한다.


이렇게 presentaion / container 컴포넌트 디렉토리 패턴은 상태 로직과 UI 로직을 분리시켜 놓아서 좀더 유지보수와 가독성을 높여준다.


위의 방식을 custom Hook으로 변경 시켜 보자


custom Hook


component

import React from "react";
import useCount from "./components/custom hook/useCount";

function Count() {
  const { num, increase, decrease } = useCount();

  return (
    <>
      <button onClick={increase}>increase</button>
      <button onClick={decrease}>decrease</button>
      <div>now count : {num}</div>
    </>
  );
}

export default Count;

custom Hook

import { useDispatch, useSelector } from "react-redux";
import { decrease_count, increase_count } from "../../modules/count";

function useCount() {
  const num = useSelector((state) => state.count.count);
  const dispatch = useDispatch();

  function increase() {
    dispatch(increase_count());
  }
  function decrease() {
    dispatch(decrease_count());
  }

  return { num, increase, decrease };
}

export default useCount;

container 컴포넌트와 다르게 custom hook으로 변경시켜 놔서 해당 로직 자체를 다른 컴포넌트에도 재사용 가능하다.


하지만 count 컴포넌트 내부에 custom hook 자체를 넣어 놓았기 때문에 UI 자체로의 재사용은 불가능하다.


정리

  • container component와 custom hook의 장점을 동시에 사용하면됨
  • presentaion component를 재사용 할 경우는 container component 사용
  • presentaion component를 재사용 하지 않으면 custom hook 사용

두 방식 모두 장단점이 있으므로 한가지 패턴으로만 사용하지 않고 적절하게 두가지 방법을 조화롭게 사용하면 각 두가지 방법의 장점을 가져 갈 수 있을것이다.


참고