
"<div id="modal-root"></div>"})"use client";
import React, { useState } from "react";
import ReactDOM from "react-dom/client"; // react-dom/client 사용
import Swal from "sweetalert2";
// 1. 외부 컴포넌트 작성
function CustomModalContent() {
const [email, setEmail] = useState("");
return (
<div className="flex flex-col gap-4">
<input
className="p-2 border rounded"
type="email"
placeholder="이메일 입력"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
);
}
export default function Page() {
// 2. ModalOpen 핸들러 작성
const onClickOpenModal = async () => {
const { isConfirmed } = await Swal.fire({
title: "회원가입",
html: "<div id='modal-root'></div>", // 모달에 React 컴포넌트 삽입할 div
showCancelButton: true,
confirmButtonText: "가입하기",
//여기부분은 그냥 암기해야겠다.
didOpen: () => {
// 순서1. 변수 선언 및 swal의 html속성에 기입한 태그를 초기화 => document.getElementById 이용
const modalRoot = document.getElementById("modal-root");
// 순서2. DOM 요소(modalRoot)가 존재하는지 확인 : 왜하는지 모르겠음 null일수 있어서 그런가봄봄
if (modalRoot) {
//순서ReactDOM.createRoot()로 root
//
ReactDOM.createRoot(modalRoot).render(<CustomModalContent />);
}
},
});
// 사용자가 "가입하기"를 클릭한 경우 처리
if (isConfirmed) {
Swal.fire({ title: "가입 완료", icon: "success" });
}
};
// 3. 버튼에 모달 Open 핸들러 등록
return (
<div className="m-auto h-screen flex flex-col justify-center items-center">
<button
className=" bg-blue-500 px-2 py-1 rounded-lg text-white"
onClick={onClickOpenModal}
>
회원가입 모달 열기
</button>
</div>
);
}
이 코드는 React와 react-hook-form, sweetalert2를 사용하여 로그인 폼을 구현하는 예제입니다. 코드의 주요 흐름을 단계별로 분석해보겠습니다.
LoginFormComponent (로그인 폼 컴포넌트)const LoginFormComponent: React.FC<{ onSubmit: (data: FormData) => void }> = ({
onSubmit,
}) => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm<FormData>();
return (
<form onSubmit={handleSubmit(onSubmit)} id="loginForm">
<div>
<label htmlFor="email">이메일:</label>
<input
id="email"
type="email"
{...register("email", { required: "이메일을 입력해주세요." })}
/>
{errors.email && <p style={{ color: "red" }}>{errors.email.message}</p>}
</div>
<div>
<label htmlFor="password">비밀번호:</label>
<input
id="password"
type="password"
{...register("password", { required: "비밀번호를 입력해주세요." })}
/>
{errors.password && (
<p style={{ color: "red" }}>{errors.password.message}</p>
)}
</div>
<button type="submit">제출</button>
</form>
);
};
useForm<FormData>(): react-hook-form에서 제공하는 훅으로, 폼 상태를 관리하고 유효성 검사(validation)를 처리합니다.register: 각 폼 필드(email, password)를 useForm과 연결시켜 주는 함수.handleSubmit: 폼 제출 시 호출되는 함수로, 유효성 검사를 통과한 후 onSubmit 콜백을 실행.formState.errors: 폼 필드에서 발생한 유효성 검사 오류들을 관리하는 객체.<input> 요소: register 함수로 각 필드에 대해 유효성 검사를 설정 (required: "이메일을 입력해주세요.", required: "비밀번호를 입력해주세요.").LoginForm (모달을 여는 메인 컴포넌트)const LoginForm: React.FC = () => {
const onSubmit = (data: FormData) => {
Swal.fire({
title: "입력한 값",
html: `
<p>이메일: ${data.email}</p>
<p>비밀번호: ${data.password}</p>
`,
icon: "success",
});
};
const openModal = () => {
Swal.fire({
title: "로그인",
html: '<div id="modal-container"></div>', // 빈 div에 컴포넌트를 삽입
showConfirmButton: false, // 확인 버튼 숨기기
didOpen: () => {
const container = document.getElementById("modal-container");
if (container) {
// createRoot가 제대로 동작하도록 보장
const root = ReactDOM.createRoot(container as HTMLElement); // 타입 명시
root.render(<LoginFormComponent onSubmit={onSubmit} />);
}
},
});
};
return (
<div className="m-auto h-screen flex flex-col justify-center items-center">
<button
className="bg-blue-300 text-white rounded-lg px-2 py-1"
onClick={openModal}
>
모달 열기
</button>
</div>
);
};
onSubmit: LoginFormComponent에서 폼 제출 후 호출되는 함수입니다. SweetAlert2의 Swal.fire를 사용해 제출된 데이터를 화면에 표시합니다.openModal: SweetAlert2 모달을 여는 함수입니다.Swal.fire로 모달을 표시하고, html 속성에 빈 <div id="modal-container"></div>를 넣어 로그인 폼을 삽입할 위치를 지정합니다.didOpen 콜백에서 modal-container div에 LoginFormComponent를 렌더링합니다. ReactDOM.createRoot를 사용하여 React 컴포넌트를 모달 안에 렌더링합니다.openModal 함수는 버튼 클릭 시 실행되어 모달을 열고, 그 안에 로그인 폼을 동적으로 삽입합니다.Swal.fire는 모달을 띄우는 라이브러리입니다. 이 코드에서는 html 속성으로 HTML 구조를 설정하고, didOpen 콜백에서 해당 HTML에 React 컴포넌트를 렌더링하여 모달 안에 로그인 폼을 동적으로 표시합니다.