안녕하세요 이번에 작성하게 될 내용은 제가 react-native에서 개발한 useComfirm custom hook에 대해 공유하고자 글을 작성하게 되었습니다.
💻 개발 환경
React-native(expo) + TypeScript로 진행되었습니다.
🧐 구현하게 된 계기
React Native 앱 개발 과정에서 흔히 마주치는 UI 구성 요소인 모달과 오버레이를 더욱 스마트하게 관리할 수 있는 방법에 대해 이야기해보려 합니다. 특히, 반복되는 Dialog 생성 코드의 중복을 줄이기 위해 커스텀 훅을 만들어 관리하는 경험을 공유하려고 합니다.
특히나 현재 저희 서비스에는 삭제/닫기를 통해 사용자에게 확인을 하는 Flow가 다수 존재했습니다.
사용자에게 선택을 요구하는 다양한 상황에서 Dialog 컴포넌트를 자주 사용하게 되었습니다. 처음에는 각 시나리오에 맞춰 Dialog 생성 코드를 반복해서 작성했습니다. 이 과정에서 코드의 중복이 불가피하게 발생하고, 유지 보수의 효율성이 떨어진다는 문제에 직면했습니다.
React Native useModal 구현하기
https://yun-tech-diary.tistory.com/entry/React-Native-useModal-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0
React Native useModal 구현하기
안녕하세요 이번에 회사 앱에 flow를 깊게 확인하기 위해 이것저것 해보는 와중 제 눈에 띈 것이 하나 있습니다. 바로 Modal 입니다. Modal은 앱에서 흔히 볼 수 있는 UI입니다. Modal을 사용하는 곳에
yun-tech-diary.tistory.com
React Native useOverlay를 만들어 리팩토링 하기 이 글은 진짜 떠야 해
React Native useOverlay를 만들어 리팩토링 하기 이 글은 진짜 떠야 해
안녕하세요 이번에 작성하게 될 내용은 제가 react-native에서 useOverlay라는 custom hook을 구현한 과정과 어떤 식으로 구현했는지에 대해 글을 작성해 보도록 하겠습니다. 💻 개발 환경 React-native(expo)
yun-tech-diary.tistory.com
그동안 Dialog를 효율적으로 관리하기 위해 이런 시도들을 했었습니다.
이번에도 새로운 시도를 해볼까 합니다.
🤔 기능 산출 및 개발 계획
정적인 Dialog를 편리하게 사용하기 위해 제가 전에 useOverlay를 구현했었습니다.
이번에 만들 Dialog는 사용자에게 단순 삭제/닫기 의사 결정만 확인하니 정적인 Dialog로서 useOverlay를 활용해서 만들 계획을 세웠습니다.
그렇다면 해당 Dialog들에서 유연하게 변경되어야 하는 부분은 무엇일까요?
바로 Dialog의 Title과 Content 내용 또 삭제 버튼을 눌렀을 때 발생할 callback event입니다.
- blue : Dialog Title 내용
- red : Dialog Content 내용
- yellow : 삭제 버튼 callback event 발생
- green : Dialog Close
이런 식으로 정리해 볼 수 있습니다.
정리한 내용을 바탕으로 개발을 진행해 보겠습니다.
👀 Custom hook 개발(CODE)
import Dialog from '../components/ui/Dialog';
import useOverlay from './overlay/useOverlay';
interface DialogContents {
title?: string;
content?: string;
}
const useConfirmDeletion = () => {
const overlay = useOverlay();
const openDialog = (
{ title, content }: DialogContents,
onRemoveHandler: () => void
) => {
overlay.open(
<Dialog isOpened={true}>
{title && <Dialog.Title title={title} />}
{content && <Dialog.Content content={content} />}
<Dialog.Buttons
buttons={[
{
label: '삭제',
onPressHandler: () => {
overlay.close();
onRemoveHandler();
},
},
{
label: '취소',
onPressHandler: () => {
overlay.close();
},
},
]}
/>
</Dialog>
);
};
return openDialog;
};
export default useConfirmDeletion;
코드 설명
- useOverlay 훅 사용: 애플리케이션의 다른 부분에서 정의된 useOverlay 훅을 사용하여 다이얼로그 레이어를 관리합니다. 이는 다이얼로그가 애플리케이션의 다른 UI 요소 위에 올바르게 표시되도록 합니다.
- openDialog 함수: openDialog는 DialogContents 객체와 삭제를 처리하는 콜백 함수 onRemoveHandler를 인자로 받습니다. DialogContents는 선택적으로 다이얼로그의 title과 content를 정의합니다.
- 다이얼로그 내용 동적 생성: 전달된 title과 content를 기반으로 다이얼로그 내용을 동적으로 생성합니다. title이나 content가 존재하는 경우에만 해당 섹션이 렌더링 됩니다.
- 삭제 및 취소 버튼: 사용자에게 제공되는 두 버튼("삭제", "취소")은 사용자가 선택할 수 있는 옵션을 제공합니다. 각 버튼에는 클릭 이벤트 핸들러가 연결되어 있으며, "삭제" 버튼을 클릭하면 onRemoveHandler가 호출되고, "취소" 버튼을 클릭하면 다이얼로그가 닫힙니다.
✨ 완성된 useConfirmDeletion
예제 코드
import React, { useState } from 'react';
import Container from '../components/layout/Container';
import { View } from 'react-native';
import Button from '../components/ui/buttons/Button';
import useConfirmDeletion from '../hooks/useConfirmDeletion';
const Screen = () => {
const confirmDeletion = useConfirmDeletion();
const [isOn, setIsOn] = useState(false);
return (
<Container>
<View
style={{
width: 100,
height: 100,
backgroundColor: isOn ? 'red' : 'blue',
}}
></View>
<Button
label='open confirmDeletion'
onPressHandler={() => {
confirmDeletion({ title: 'title', content: 'content' }, () => {
setIsOn(true);
});
}}
/>
</Container>
);
};
export default Screen;
예제 코드 설명
"open ConfirmDeletion"이라는 Button을 Press 시 useConfirmDeletion hook을 이용하여 Dialog를 사용자에게 노출시킵니다.
"삭제"라는 버튼 클릭 시 isOn이라는 state 값이 변경되어 View로 생성된 Box의 backgroundColor가 blue에서 red로 변경됩니다.
실행 결과
😁 글 작성 후기
오늘도 간단한 custom hook을 들고 왔습니다만 실제로 스크린에서 글 삭제 로직이 있는 곳에서 유용하게 사용 중입니다.
이 custom hook이 간단하게 구현됐던 이유 중 하나인 제가 이전에 Overlay 계열의 컴포넌트를 손쉽게 관리하기 위해 개발했던 useOverlay를 구현해 놨기 때문인데요 다른 분들도 custom hook을 만들 때 이전에 만들었던 custom hook을 활용해서 더 유용한 custom hook을 만들어 보는 기회를 가져보는 것도 좋은 경험이 될 것 같습니다.
'개발' 카테고리의 다른 글
나의 노력이 만든 CS팀의 만족 (1) | 2024.05.30 |
---|---|
돈이 새고 있었어 API 호출 최적화로 성능 개선하기 (0) | 2024.03.14 |
React Native useImageAspectRatio 이미지 비율을 계산하는 hook (0) | 2024.01.30 |
나의 JWT 이야기 (1) | 2024.01.08 |
AppBar 컴포넌트 리팩토링 이야기 (0) | 2023.12.14 |