Container, Presenter Design Pattern

issol·2021년 2월 4일
0

Learned

목록 보기
1/2

Container, Presenter 디자인 패턴?

간단하게 데이터처리와, 데이터 출력을 분리하는거다.
Container : API Request, Exception Error, setState... ETC...
Presenter : only Props, UI, no logic

예시

container

import React from 'react'

import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useForm } from 'react-hook-form';

import { RootState } from 'store';
import { logIn } from 'store/users/actions';
import LogInPresenter from './presenter';
import StatusModal from 'components/StatusModal';
import { LogInInfo } from 'store/users/types';

const LogInContainer = () => {
  const dispatch = useDispatch();
  const [isOpenModal, setIsOpenModal] = useState(false);
  const [errorMessage, setErrorMessage] = useState('');

  const userReducer = useSelector((state: RootState) => state.userReducer);

  const { register, errors, handleSubmit } = useForm<LogInInfo>();

  const handleLogin = (data) => {
    dispatch(logIn.request(data));
  };

  useEffect(() => {
    if (userReducer.errorMessage !== '') {
      setErrorMessage(userReducer.errorMessage);
      setIsOpenModal(true);
    }
  }, [userReducer.errorMessage]);

  return (
      <LogInPresenter
        onSubmit={handleLogin}
        handleSubmit={handleSubmit}
        register={register}
        errors={errors}
      />
  );
};

export default LogInContainer;

Container에는 데이터처리를 위한 state관리나 api request등만 정의되 있고, 화면 출력을 위해 Presenter를 상속받아 필요한 Props를 넘겨준다.

Presenter

import React from 'react';
import TextInput from 'components/TextInput';

import { DeepMap, FieldError } from 'react-hook-form';
import styled from 'styled-components';

type inputProps = {
  email: string;
  password: string;
};

type RefReturn =
  | string
  | ((instance: HTMLInputElement | null) => void)
  | React.RefObject<HTMLInputElement>
  | null
  | undefined;

type Props = {
  onSubmit: (event: React.FormEvent<HTMLFormElement>) => void;
  handleSubmit: Function;
  register: ({ required }: { required?: boolean }) => RefReturn;
  errors: DeepMap<inputProps, FieldError>;
};

const LogInPresenter = ({
  onSubmit,
  handleSubmit,
  register,
  errors,
### }: Props) => {
  return (
    <LoginForm onSubmit={handleSubmit(onSubmit)} className="input-group">
      <TextInput type="email" label="email" register={register} required />
      {errors.email && <ErrorMessage>⚠이메일을 입력해주세요</ErrorMessage>}
      <TextInput
        type="password"
        label="password"
        register={register}
        required
      />
      {errors.password && <ErrorMessage>⚠비밀번호를 입력해주세요</ErrorMessage>}
      <LoginButton type="submit" className="login" value="Login" />
    </LoginForm>
  );
};

Presenter는 Container가 넘겨준 Props를 가지고 데이터를 출력하고, 화면을 구성하게 된다.

index.ts

import LogInContainer from './container';

export default LogInContainer;

그 덕분에 index는 굉장히 간결해졌다. Container를 상속해서 다른 컴포넌트에서 사용할 수 있도록 export해주면 끝!

Container, Presenter 패턴도 적용하니 개발을 할 때 가독성이 좋아지고, 관리가 굉장히 편해졌다. 물론 Typescript를 사용하고 있기 때문에, Type지정하는게 처음엔 굉장히 익숙치 않았다. 하지만 적응되니 내가 볼때도 편하고 나중에 이게 뭐였지? 하며 고민하는 일도 줄었다. 다음엔 사용한 React Hook에 대해 정리하고자 한다.

profile
Junior Front-End Developer

0개의 댓글