Skip to content

Commit 8515d7d

Browse files
authored
Merge pull request #125 from codeit-maso/feature/Yun
offset 문제 수정 및 모달 바깥 클릭시 닫히는 기능 추가
2 parents 6d60b62 + 9e3e35f commit 8515d7d

File tree

3 files changed

+43
-18
lines changed

3 files changed

+43
-18
lines changed

src/components/Modal/Modal.jsx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import { useState } from 'react';
1+
import { useRef, useState, useEffect, useCallback } from 'react';
22
import DOMPurify from 'dompurify';
33
import ReactDOM from 'react-dom';
44
import Badge from '../Badge/Badge';
55
import Button from '../common/Button';
6+
import useModalClose from '../../hooks/useModalClose'; // 경로에 맞게 수정
67
import styles from './Modal.module.scss';
78

89
export default function Modal({
@@ -14,19 +15,27 @@ export default function Modal({
1415
createdAt,
1516
onClose,
1617
}) {
18+
const modalRef = useRef(null);
1719
const [isClosing, setIsClosing] = useState(false);
1820
const sanitizedHTML = DOMPurify.sanitize(children);
1921

20-
const handleCloseModal = () => {
22+
// 닫기 로직 (애니메이션 포함)
23+
const handleCloseModal = useCallback(() => {
2124
setIsClosing(true);
2225
setTimeout(() => {
2326
onClose();
2427
}, 300);
25-
};
28+
}, [onClose]);
29+
30+
// 외부 클릭 감지하여 닫기
31+
useModalClose(modalRef, handleCloseModal);
2632

2733
return ReactDOM.createPortal(
2834
<div className={styles.backdrop}>
29-
<article className={`${styles.modal} ${isClosing ? styles.closing : ''}`}>
35+
<article
36+
ref={modalRef}
37+
className={`${styles.modal} ${isClosing ? styles.closing : ''}`}
38+
>
3039
<header className={styles['modal__header']}>
3140
<div className={styles['modal__profile-img']}>
3241
<img src={image} alt="프로필 이미지" />

src/hooks/useModalClose.jsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { useEffect } from 'react';
2+
3+
export default function useDetectClose(ref, onClose) {
4+
useEffect(() => {
5+
const handleClick = (e) => {
6+
if (ref.current && !ref.current.contains(e.target)) {
7+
onClose(); // 바로 닫기 말고 외부에서 애니메이션 포함한 onClose 실행
8+
}
9+
};
10+
document.addEventListener('mousedown', handleClick);
11+
return () => {
12+
document.removeEventListener('mousedown', handleClick);
13+
};
14+
}, [ref, onClose]);
15+
}

src/pages/Recipient/Recipient.jsx

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -50,21 +50,21 @@ export default function Recipient({ showDelete }) {
5050
new Map(combined.map((message) => [message.id, message])).values(),
5151
);
5252

53-
return uniqueMessages;
54-
});
55-
56-
if (showDelete) {
57-
setMessages(allMessages);
58-
} else {
59-
if (
60-
allMessages.length % 6 === 0 &&
61-
allMessages.length !== newMessages.count
62-
) {
63-
setMessages(allMessages.slice(0, allMessages.length - 1));
53+
if (showDelete) {
54+
setMessages(uniqueMessages);
6455
} else {
65-
setMessages(allMessages);
56+
if (
57+
uniqueMessages.length % 6 === 0 &&
58+
uniqueMessages.length !== newMessages.count
59+
) {
60+
setMessages(uniqueMessages.slice(0, uniqueMessages.length - 1));
61+
} else {
62+
setMessages(uniqueMessages);
63+
}
6664
}
67-
}
65+
66+
return uniqueMessages;
67+
});
6868
if (!postData) return;
6969
setHasNextMessage(offset < postData.messageCount);
7070
setLoading(false);
@@ -82,6 +82,7 @@ export default function Recipient({ showDelete }) {
8282
useEffect(() => {
8383
const observer = new IntersectionObserver((entries) => {
8484
const firstEntry = entries[0];
85+
8586
if (firstEntry.isIntersecting && hasNextMessage && !loading) {
8687
loadMoreMessages();
8788
}
@@ -126,7 +127,7 @@ export default function Recipient({ showDelete }) {
126127
}
127128

128129
function handleGoBack() {
129-
navigate(-1);
130+
showDelete ? navigate(`/post/${id}/`) : navigate('/list');
130131
}
131132

132133
function handleEditClick(id) {

0 commit comments

Comments
 (0)