Refactor TransactionDeleteAlert component

Refactor TransactionDeleteAlert component to improve maintainability.
This commit is contained in:
gpt-engineer-app[bot]
2025-03-21 10:06:03 +00:00
parent c473abda72
commit 9352b1bb27
2 changed files with 81 additions and 60 deletions

View File

@@ -1,5 +1,5 @@
import React, { useState, useRef, useEffect } from 'react'; import React from 'react';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Trash2, Loader2 } from 'lucide-react'; import { Trash2, Loader2 } from 'lucide-react';
import { import {
@@ -13,75 +13,22 @@ import {
AlertDialogTitle, AlertDialogTitle,
AlertDialogTrigger AlertDialogTrigger
} from '@/components/ui/alert-dialog'; } from '@/components/ui/alert-dialog';
import { useDeleteAlert } from '@/hooks/transactions/useDeleteAlert';
interface TransactionDeleteAlertProps { interface TransactionDeleteAlertProps {
onDelete: () => Promise<boolean> | boolean; onDelete: () => Promise<boolean> | boolean;
} }
/** /**
* 트랜잭션 삭제 확인 다이얼로그 - 완전히 개선된 버전 * 트랜잭션 삭제 확인 다이얼로그 - 리팩토링된 버전
* 삭제 중복 방지, 상태 관리 개선, 메모리 누수 방지 로직 추가 * 삭제 로직을 useDeleteAlert 훅으로 분리하여 컴포넌트 간소화
*/ */
const TransactionDeleteAlert: React.FC<TransactionDeleteAlertProps> = ({ onDelete }) => { const TransactionDeleteAlert: React.FC<TransactionDeleteAlertProps> = ({ onDelete }) => {
const [isOpen, setIsOpen] = useState(false); // 삭제 관련 로직을 커스텀 훅으로 분리
const [isDeleting, setIsDeleting] = useState(false); const { isOpen, isDeleting, handleDelete, handleOpenChange } = useDeleteAlert(onDelete);
// 타임아웃 참조 저장 (메모리 누수 방지용)
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
// 클린업 함수 - 메모리 누수 방지
const clearTimeouts = () => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
timeoutRef.current = null;
}
};
// 컴포넌트 언마운트 시 모든 타임아웃 제거
useEffect(() => {
return () => {
clearTimeouts();
};
}, []);
const handleDelete = async () => {
// 이미 삭제 중이면 중복 실행 방지
if (isDeleting) return;
try {
// 삭제 상태 활성화
setIsDeleting(true);
// 다이얼로그 즉시 닫기 (UI 응답성 개선)
setIsOpen(false);
// UI 애니메이션 완료 후 삭제 실행
timeoutRef.current = setTimeout(async () => {
try {
// 삭제 함수 실행
await onDelete();
} catch (error) {
console.error('삭제 처리 오류:', error);
} finally {
// 모든 작업 완료 후 상태 초기화 (약간 지연)
timeoutRef.current = setTimeout(() => {
setIsDeleting(false);
}, 100);
}
}, 150);
} catch (error) {
console.error('삭제 핸들러 오류:', error);
setIsDeleting(false);
setIsOpen(false);
}
};
return ( return (
<AlertDialog open={isOpen} onOpenChange={(open) => { <AlertDialog open={isOpen} onOpenChange={handleOpenChange}>
// 삭제 중에는 상태 변경 방지
if (isDeleting && !open) return;
setIsOpen(open);
}}>
<AlertDialogTrigger asChild> <AlertDialogTrigger asChild>
<Button <Button
type="button" type="button"

View File

@@ -0,0 +1,74 @@
import { useState, useRef, useEffect } from 'react';
/**
* 트랜잭션 삭제 알림 관련 로직을 담당하는 커스텀 훅
*/
export const useDeleteAlert = (onDelete: () => Promise<boolean> | boolean) => {
const [isOpen, setIsOpen] = useState(false);
const [isDeleting, setIsDeleting] = useState(false);
// 타임아웃 참조 저장 (메모리 누수 방지용)
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
// 클린업 함수 - 메모리 누수 방지
const clearTimeouts = () => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
timeoutRef.current = null;
}
};
// 컴포넌트 언마운트 시 모든 타임아웃 제거
useEffect(() => {
return () => {
clearTimeouts();
};
}, []);
const handleDelete = async () => {
// 이미 삭제 중이면 중복 실행 방지
if (isDeleting) return;
try {
// 삭제 상태 활성화
setIsDeleting(true);
// 다이얼로그 즉시 닫기 (UI 응답성 개선)
setIsOpen(false);
// UI 애니메이션 완료 후 삭제 실행
timeoutRef.current = setTimeout(async () => {
try {
// 삭제 함수 실행
await onDelete();
} catch (error) {
console.error('삭제 처리 오류:', error);
} finally {
// 모든 작업 완료 후 상태 초기화 (약간 지연)
timeoutRef.current = setTimeout(() => {
setIsDeleting(false);
}, 100);
}
}, 150);
} catch (error) {
console.error('삭제 핸들러 오류:', error);
setIsDeleting(false);
setIsOpen(false);
}
};
// 다이얼로그 상태 관리
const handleOpenChange = (open: boolean) => {
// 삭제 중에는 상태 변경 방지
if (isDeleting && !open) return;
setIsOpen(open);
};
return {
isOpen,
isDeleting,
handleDelete,
handleOpenChange
};
};