잡탕_Modal_Sweetalert2 라이브러리_2

김형준·2025년 3월 31일
post-thumbnail

1. 외부의 컴포넌트 또는 태그를 이용하여, 모달에 넣어보기

순서1 : swal({... html : "<div id="modal-root"></div>"})

순서2 : swal({... didOpen : 콜백함수 ()=>{...}})

순서3 : {...}의 구현부_1 : document.getElementById로 modal-root 태그를 변수로 초기화

순서4 : {...}의 구현부_2 : if(modal-root){ReactDOM.createRoot(modalRoot).render(외부컴포넌트)}

예시:

"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>
  );
}

실행 화면


녹화_2025_03_31_14_49_01_862.gif

응용2. useForm + ReactDOM + sweetalert2 으로 로그인 모달 만들기

이 코드는 React와 react-hook-form, sweetalert2를 사용하여 로그인 폼을 구현하는 예제입니다. 코드의 주요 흐름을 단계별로 분석해보겠습니다.

1. 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: "비밀번호를 입력해주세요.").
  • 에러 메시지 출력: 유효성 검사에서 실패한 경우, 오류 메시지가 빨간색으로 표시됩니다.

2. 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 함수는 버튼 클릭 시 실행되어 모달을 열고, 그 안에 로그인 폼을 동적으로 삽입합니다.

3. 모달 사용

  • SweetAlert2의 Swal.fire는 모달을 띄우는 라이브러리입니다. 이 코드에서는 html 속성으로 HTML 구조를 설정하고, didOpen 콜백에서 해당 HTML에 React 컴포넌트를 렌더링하여 모달 안에 로그인 폼을 동적으로 표시합니다.

실행 화면

녹화_2025_03_31_17_00_33_882.gif


profile
로으앞 근차근차

0개의 댓글