From 0780410506d4ec2fc51ea0d836ee1024e150dcb1 Mon Sep 17 00:00:00 2001 From: syc0123 Date: Tue, 31 Mar 2026 16:19:48 +0900 Subject: [PATCH] =?UTF-8?q?[RAPID-fix]=20=EC=8A=A4=ED=81=AC=EB=A1=A4=20sen?= =?UTF-8?q?tinel=20=EB=B0=A9=EC=8B=9D=EC=9C=BC=EB=A1=9C=20=EA=B5=90?= =?UTF-8?q?=EC=B2=B4:=20scrollIntoView=20useLayoutEffect=20(=ED=8E=98?= =?UTF-8?q?=EC=9D=B8=ED=8A=B8=20=EC=A0=84=20=EB=B3=B4=EC=9E=A5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/components/messenger/ChatPanel.tsx | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/frontend/components/messenger/ChatPanel.tsx b/frontend/components/messenger/ChatPanel.tsx index df6ca66a..784f6561 100644 --- a/frontend/components/messenger/ChatPanel.tsx +++ b/frontend/components/messenger/ChatPanel.tsx @@ -23,7 +23,7 @@ export function ChatPanel({ room }: ChatPanelProps) { const { emitTypingStart, emitTypingStop, typingUsers } = useMessengerSocket(); const scrollRef = useRef(null); const [isAtBottom, setIsAtBottom] = useState(true); - const [scrollReady, setScrollReady] = useState(false); + const bottomRef = useRef(null); const [isEditingName, setIsEditingName] = useState(false); const [editName, setEditName] = useState(""); const editInputRef = useRef(null); @@ -36,22 +36,14 @@ export function ChatPanel({ room }: ChatPanelProps) { const lastMessageId = messages?.[messages.length - 1]?.id; - // useLayoutEffect: fires before browser paint → hide + scroll synchronously + // Scroll to bottom: sentinel scrollIntoView before paint (no visible jump) useLayoutEffect(() => { - const el = scrollRef.current; - if (!el) return; - setScrollReady(false); - el.scrollTop = el.scrollHeight; - // Reveal after scroll is applied - requestAnimationFrame(() => setScrollReady(true)); + bottomRef.current?.scrollIntoView(); }, [selectedRoomId, lastMessageId]); - // Second pass: re-scroll after async images load + // Second pass for async image loads useEffect(() => { - const t = setTimeout(() => { - const el = scrollRef.current; - if (el) el.scrollTop = el.scrollHeight; - }, 600); + const t = setTimeout(() => { bottomRef.current?.scrollIntoView(); }, 600); return () => clearTimeout(t); }, [lastMessageId, selectedRoomId]); @@ -167,7 +159,7 @@ export function ChatPanel({ room }: ChatPanelProps) { {/* Messages */} -
+
{messages?.map((msg, idx) => (
@@ -196,6 +188,7 @@ export function ChatPanel({ room }: ChatPanelProps) {
{roomTyping && roomTyping.length > 0 ? `${roomTyping.join(", ")}님이 입력 중...` : ""}
+