🤔 서론
보통 모바일에서 많이 쓰이지만 한 번도 구현해본적 없는 기능을 구현해보려 했다. 항상 모달창에 x버튼을 두고 클릭하면 꺼지게 했는데 모바일에서 사용할 것을 대비하여 버튼 없이 기능이 작동하게 하려 한다.
🥅 목표
- 모달 창 바깥 배경을 클릭했을 때 모달 창 꺼지기
👩🏻💻 구현
전체 코드
// 모달 창
import React from "react";
import { FiThumbsDown, FiThumbsUp } from "react-icons/fi";
interface propsType {
modalRef: React.ForwardedRef<HTMLDivElement>;
modalOutsideClicked: (e: any) => void;
cardId?: string;
userId?: string;
}
export default function CardDetail({
modalRef,
modalOutsideClicked,
cardId,
userId,
}: propsType) {
return (
<div
className="fixed inset-0 bg-black bg-opacity-60"
ref={modalRef}
onClick={(e) => modalOutsideClicked(e)}
>
<div
className="
absolute top-1/2 left-1/2 transform -translate-y-2/3 -translate-x-1/2 bg-white flex-col justify-start w-1/2 h-3/6 border-2 border-current"
>
...
</div>
</div>
);
}
import React, { useEffect, useRef, useState } from "react";
import { FiThumbsUp, FiThumbsDown } from "react-icons/fi";
import { GET } from "@/axios/GET";
import CardDetail from "./CardDetail";
export default function Feeds() {
const [cards, setCards] = useState([]);
// 모달
const modalRef = useRef<HTMLDivElement>(null);
const [showModal, setShowModal] = useState(false);
const [cardId, setCardId] = useState(1);
...
const modalOutsideClicked = (e: any) => {
if (modalRef.current === e.target) {
setShowModal(false);
}
};
return (
<div>
<p className="text-3xl font-semibold">피드</p>
...
{showModal && (
<CardDetail
modalRef={modalRef}
modalOutsideClicked={modalOutsideClicked}
cardId={cardId}
/>
)}
</div>
);
}
부가 설명
const modalOutsideClicked = (e: any) => {
if (modalRef.current === e.target) {
setShowModal(false);
}
};
- modalRef.current는 ref 객체가 실제로 참조하고 있는 DOM요소를 나타낸다. 현재는 모달 바깥을 감싸고 있는 <div>를 참조하고 있다. e.target은 사용자가 클릭한 실제 HTML요소를 나타낸다. 즉, 해당 조건문은 사용자가 모달 바깥 <div>를 클릭했는지 확인한다.
- 위의 조건문이 참인 경우, 즉 사용자가 모달 외부를 클릭한 경우 setShowModal(false)를 통해 모달 창을 닫는다.
{showModal && (
<CardDetail
modalRef={modalRef}
modalOutsideClicked={modalOutsideClicked}
cardId={cardId}
/>
)}
- showModal이 true면 CardDetail 컴포넌트를 보인다.
- CardDetail 컴포넌트에는 modalRef, modalOutsideClicked를 props로 보낸다. 해당 props는 CardDetail 컴포넌트에서 type을 정의한다.
interface propsType {
modalRef: React.ForwardedRef<HTMLDivElement>;
modalOutsideClicked: (e: any) => void;
cardId?: string;
userId?: string;
}
- modalRef: React.ForwardedRef<HTMLDivElement>
React의 ForwardedRef를 사용하여 참조(Ref)를 전달 받고, 이 참조는 HTMLDivElement에 연결된다.(HTML의 <div>요소를 참조한다는 것을 나타낸다.) 이를 통해 다른 곳에서 이 참조를 사용하여 DOM요소에 직접 접근할 수 있다.
<div
className="fixed inset-0 bg-black bg-opacity-60"
ref={modalRef}
onClick={(e) => modalOutsideClicked(e)}
>
<div
className="
absolute top-1/2 left-1/2 transform -translate-y-2/3 -translate-x-1/2 bg-white flex-col justify-start w-1/2 h-3/6 border-2 border-current"
>
...
</div>
</div>
- 바깥 배경에 참조를 걸면 기능이 작동하는 것을 볼 수 있다.
✨ 결과
참고자료
'W > CSS' 카테고리의 다른 글
TailwindCSS 시작하기 (0) | 2024.07.17 |
---|---|
[React/CSS] instagram 스토리처럼 드래그로 요소 넘기기 (0) | 2024.07.17 |