btn, popup 공통 컴포넌트 작업하기
공통 컴포넌트 Button, Popup 창
작성: 2023년 7월 4일
- 목차
Button 컴포넌트 구현
공통적으로 사용할 버튼 컴포넌트를 만들기 위해서 어떤 prop을 전달해야 하고, 어떤 형식으로 작성이 되어야 하는지 고민을 하였습니다. 총 고려해야 하는 점은 4가지 였습니다.
- 버튼의 크기
- 버튼의 배경색
- 버튼의 문구
- 버튼의 기능
- 버튼 활성화 여부
따라서 위의 4가지 요소는 prop으로 전달하여 사용하는 목적에 따라 결정하는 방향으로 작성을 하였습니다.
- 크기의 경우는 가장 큰 크기, 중간 크기, 작은 크기 3가지 만을 고려하기에 TS를 통해 오직 ‘lg’, ‘md’. ‘sm’ 에 해당되는 값들만을 받도록 하였습니다.
- 버튼의 배경색은 흰색과 저희의 태마색인 초록색 만을 활용합니다. 이러한 이유로 ‘true’, ‘false’ 값을 전달하도록 처리하였습니다.
- 버튼의 문구는 어떤 문자열이어도 가능하도록 처리하였습니다.
- 버튼의 기능은 callback 함수를 prop으로 전달해서, 클릭 되었을 때, 해당 함수가 실행될 수 있도록 작성을 하였습니다. 또한 버튼에 특정 handler가 필요 없는 경우를 고려하여 prop의 option을 optional로 설정을 하였습니다.
- 마지막으로 버튼 활성화 여부를 결정하는 변수를 작성하였습니다. 이에 따라 버튼 활성화 여부를 결정할 수 있도록 만들었습니다.
Button 코드
import { BooleanStr, Size, Handler } from '../../types/propType.ts';
import { Btn } from './button.styled.tsx';
interface Prop {
size: Size; //lg, md, sm
text: string;
isgreen: BooleanStr; // true, false
handler?: Handler; // ()=>void
disabled?: boolean;
}
export default function Button({
size,
text,
isgreen,
handler,
disabled,
}: Prop) {
const voidFn = () => {
// 빈함수
};
return (
<Btn
isgreen={isgreen}
size={size}
onClick={handler ? handler : voidFn}
disabled={disabled === undefined ? false : disabled ? true : false}>
{text}
</Btn>
);
}Pop-up 컴포넌트 구현
popup 컴포넌트는 대부분의 작업에서 사용이 되었습니다. 가령 api 과정중에 error가 발생했을 시 사용자에게 이를 알려주기 위해 팝업창을 띄어야 했습니다. 혹은 특정 작업에 성공했을 때에도 Pop-up창을 띄워야 했습니다. window에 내장된 alert를 사용할 수도 있지만, 디자인적으로 예쁘지 않다고 생각하여 직접 작성한 팝업창을 띄우는 것으로 결정을 했습니다. 이때 팝업창에 사용되는 버튼은 공통 컴포넌트로 구현한 버튼 컴포넌트를 활용하고자 하였습니다.
고민
- 팝업 컴포넌트에 몇 개의 버튼을 사용하도록 하여야 할까?
- 대부분의 경우 확인, 닫기 등의 기능이 있기 때문에, 버튼의 개수는 최소 1개 2개 까지 유동적으로 선택할 수 있도록 구현해야 했습니다.
- 버튼의 개수가 늘어난다면, 몇 개의 handler를 사용해야 할까?
- 팝업 창의 외곽을 클릭하면 팝업 창이 닫혀야 하므로 이에 따른 state를 넘겨주어야 하였으며, 추가적으로 각 버튼의 handler(function) 또한 전달이 되어야 했습니다.
- 버튼의 개수에 따라 유동적으로 handler가 전달이 되어야 한다는 점을 고려 해야 했습니다.
- popup 컴포넌트를 통제하는 state를 전역으로 관리를 해야할까? 아니면 각 페이지 별로 관리를 해야할까?
- pop-up창을 열었다 닫았다 할 수 있는 controller 역할을 하는 state 값이 필요로 했습니다.
- 이를 전역 state로 관리하는 것을 고민했습니다. 만약 전역 state로 관리를 해야 한다면, popup창을 조절할 boolean값 하나와 각 popup별 역할이 다르기 때문에 popup창의 기능과 글을 전달할 전역 state 총 두 가지를 필요로 했습니다. 하지만 각각의 페이지에서 popup을 호출할 상황이 모두 달랐습니다. 즉 공통적으로 사용하는 글귀가 거의 없었습니다. 게시글을 삭제 하는 경우 외에는 상황에 따라 다른 오류 안내, 성공 안내를 해야 했기 때문입니다. 이러한 이유로 같은 코드와 state의 반복이지만 전역으로 관리하지 않고 각각의 페이지 별로 관리하는 방향으로 코드를 작성하였습니다.
- 대부분의 prop 값을 array 형태로 받아서 처리하는 형태로 작성을 하게 되었습니다.
Pop-up 코드 작성
import { BooleanStr, Size, Handler } from '../../types/propType.ts';
import Button from '../button/Button.tsx';
import {
PopupBackGround,
PopupBox,
Title,
ButtonBox,
} from './popup.styled.tsx';
interface Prop {
title: string;
handler: Handler[];
isgreen: BooleanStr[];
btnsize: Size[];
buttontext: string[];
countbtn: 1 | 2;
popupcontrol: Handler;
}
export default function Popup({
title,
handler,
isgreen,
btnsize,
buttontext,
countbtn,
popupcontrol,
}: Prop) {
return (
<>
<PopupBackGround
onClick={e => {
e.preventDefault();
popupcontrol();
}}>
<PopupBox
onClick={e => {
e.stopPropagation();
}}>
<Title>{title}</Title>
<ButtonBox countbtn={`${countbtn}`}>
{countbtn === 1 && (
<Button
size={btnsize[0]}
isgreen={isgreen[0]}
text={buttontext[0]}
handler={handler[0]}
/>
)}
{countbtn === 2 && (
<>
<Button
size={btnsize[0]}
isgreen={isgreen[0]}
text={buttontext[0]}
handler={handler[0]}
/>
<Button
size={btnsize[1]}
isgreen={isgreen[1]}
text={buttontext[1]}
handler={handler[1]}
/>
</>
)}
</ButtonBox>
</PopupBox>
</PopupBackGround>
</>
);
}Content Table
- 공통 컴포넌트 Button, Popup 창
- Button 컴포넌트 구현
- Button 코드
- Pop-up 컴포넌트 구현
- 고민
- Pop-up 코드 작성
Sharepetment
2023.07.04
8 / 9