처음 찾아본 코드로는
useEffect(() => {
document.body.style.overflow = 'hidden';
return () => {
document.body.style.overflow = 'unset';
};
}, []);
을 사용했는데
문제점은 스크롤바가 사라지면서 레이아웃이 비틸렸다 다시 돌아왔다 한다는 것
상당히 거슬려서 새로운 방법을 찾아봤다.
// utils/modal.ts
/**
* 스크롤을 방지하고 현재 위치를 반환한다.
* @returns {number} 현재 스크롤 위치
*/
export const preventScroll = (): number => {
const currentScrollY = window.scrollY;
document.body.style.position = "fixed";
document.body.style.width = "100%";
document.body.style.top = `-${currentScrollY}px`; // 현재 스크롤 위치
document.body.style.overflowY = "scroll";
return currentScrollY;
};
/**
* 스크롤을 허용하고, 스크롤 방지 함수에서 반환된 위치로 이동한다.
* @param prevScrollY 스크롤 방지 함수에서 반환된 스크롤 위치
*/
export const allowScroll = (prevScrollY: number) => {
document.body.style.position = "";
document.body.style.width = "";
document.body.style.top = "";
document.body.style.overflowY = "";
window.scrollTo(0, prevScrollY);
};
"use client";
import { deleteUser } from "@/actions/auth";
import { ErrorDisplay } from "@/components/ErrorDisplay";
import { Input } from "@/components/Input";
import { Button } from "@/components/ui/Button/Button";
import Modal from "@/components/ui/Modal";
import convertAuthSupabaseErrorToKorean from "@/error/convertAuthSupabaseErrorToKorean";
import logout from "@/utils/auth/logout";
import { AuthError } from "@supabase/supabase-js";
import { useEffect, useState } from "react";
const CHECK_TEXT = "탈퇴하겠습니다";
export default function DeleteUserModalPage() {
const [valid, setValid] = useState(false);
const handleCheckText = (e: React.ChangeEvent<HTMLInputElement>) => {
setValid(e.target.value === CHECK_TEXT);
};
const [error, setError] = useState<AuthError | null>(null);
const [unexpectedError, setUnexpectedError] = useState<Error | null>(null);
useEffect(() => {
if (unexpectedError) {
throw unexpectedError;
}
}, [unexpectedError]);
const handleDeleteUser = async () => {
if (!valid) return;
try {
const { success, error } = await deleteUser();
if (!success) {
setError(error || null);
} else {
logout();
}
} catch (error) {
setUnexpectedError(error as Error);
}
};
return (
<>
<Modal>
<Modal.Header>회원 탈퇴</Modal.Header>
<Modal.Content className="p-4">
<ErrorDisplay
message={
convertAuthSupabaseErrorToKorean(error?.code) || error?.message
}
/>
<p>회원 탈퇴 시 모든 데이터가 삭제됩니다.</p>
<p className="mb-4">
정말 탈퇴하시겠습니까? 원한다면{" "}
<span className="font-bold text-red-500">
"{CHECK_TEXT}"
</span>{" "}
를 입력하고 버튼을 눌러주세요.
</p>
<Input
type="text"
placeholder={CHECK_TEXT}
onChange={handleCheckText}
/>
</Modal.Content>
<Modal.Footer>
<Button disabled={!valid} onClick={handleDeleteUser}>
회원 탈퇴
</Button>
</Modal.Footer>
</Modal>
</>
);
}
위와 같은 유틸 함수를 만들고
useEffect를 통해 구현해주면 완성
이전 방법의 문제점이 개선되었다.
'개발 > NEXTJS' 카테고리의 다른 글
| nextjs 쿠키 옵션 설정 (1) | 2025.02.16 |
|---|---|
| supabase에서 회원 탈퇴 구현하기 (0) | 2025.02.10 |
| error.tsx 사용 (0) | 2025.02.10 |
| nextjs 에러 관리 (5) | 2025.02.05 |
| 사용자 avata image 변경했을 때 (0) | 2025.01.31 |