From c63f3e4a8b083a3617916f39b515702039e08f06 Mon Sep 17 00:00:00 2001 From: whtnqls124578 Date: Wed, 1 Nov 2023 23:33:06 +0900 Subject: [PATCH 1/6] =?UTF-8?q?feat:#226=20sse=20=EC=BB=A4=EC=8A=A4?= =?UTF-8?q?=ED=85=80=ED=9B=85=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/chat/Chat.tsx | 4 +++ src/components/chat/ChatList.tsx | 17 ++++++++++- src/hooks/useSSE.ts | 49 ++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 src/hooks/useSSE.ts diff --git a/src/components/chat/Chat.tsx b/src/components/chat/Chat.tsx index 3746eff..ed66ecf 100644 --- a/src/components/chat/Chat.tsx +++ b/src/components/chat/Chat.tsx @@ -100,10 +100,12 @@ const Chat = ({ {isCustomRoomId ? ( ) : ( @@ -124,10 +126,12 @@ const Chat = ({ {!isCustomRoomId ? ( ) : ( diff --git a/src/components/chat/ChatList.tsx b/src/components/chat/ChatList.tsx index c3b857c..cd00718 100644 --- a/src/components/chat/ChatList.tsx +++ b/src/components/chat/ChatList.tsx @@ -3,6 +3,7 @@ import { useEffect, useState } from 'react'; import { sellerChatList, userChatList } from '@/apis/chat'; import ChatBody from '@/components/chat/chatList/ChatBody'; import ChatHeader from '@/components/chat/chatList/ChatHeader'; +import { useSSE } from '@/hooks/useSSE'; import { Message } from '@/models/chat'; export type Chat = { @@ -35,13 +36,27 @@ type chatProps = { productName: string; }; isSeller: boolean; + role: string; + customRoomId: string; }; -const ChatList = ({ handleOpen, clickListBox, seller, isSeller, product }: chatProps) => { +const ChatList = ({ + handleOpen, + clickListBox, + seller, + isSeller, + product, + customRoomId, + role, +}: chatProps) => { const [list, setList] = useState([]); const [shopImg, setShopImg] = useState(''); + const message = useSSE(customRoomId, role); + + console.log(message); + const loadUserChatList: () => Promise = async () => { const sellerId = seller.sellerId; userChatList(sellerId) diff --git a/src/hooks/useSSE.ts b/src/hooks/useSSE.ts new file mode 100644 index 0000000..c943921 --- /dev/null +++ b/src/hooks/useSSE.ts @@ -0,0 +1,49 @@ +import { useEffect, useState } from 'react'; + +type chatAlarm = { + content: string; + createAt: string; + customRoomId: string; + role: string; + sellerId: number; + sender: string; +}; + +export const useSSE = (customRoomId: string, role: string) => { + console.log('useSSE', customRoomId); + console.log('role', role); + const [message, setMessage] = useState([]); + + console.log(message); + + useEffect(() => { + const eventSource = new EventSource( + `${import.meta.env.VITE_API_SSE_URL}/chat-alarm/${role}/${customRoomId}`, + ); + + eventSource.addEventListener('sse', function (event) { + const message = JSON.parse(event.data); + console.log('새로운 채팅 알람: ', message); + setMessage((prevMessages) => [...prevMessages, message]); + }); + + eventSource.onerror = function (error) { + console.error('EventSource failed:', error); + eventSource.close(); + }; + + window.addEventListener('unload', function () { + if (eventSource) { + eventSource.close(); + console.log('EventSource closed'); + } + }); + + return () => { + eventSource.close(); + console.log('EventSource closed'); + }; + }, [customRoomId, role]); + + return message; +}; From f5c3c579085192f47ec90d0888a58d41fbd9d78b Mon Sep 17 00:00:00 2001 From: whtnqls124578 Date: Thu, 2 Nov 2023 00:39:32 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat:#226=20=EA=B8=B0=EC=A1=B4=20customroom?= =?UTF-8?q?Id=20=EB=B9=84=EC=9B=8C=EC=84=9C=20chatList,chatDetail=20?= =?UTF-8?q?=EB=B6=84=EA=B8=B0=EC=B2=98=EB=A6=AC=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/chat/Chat.tsx | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/src/components/chat/Chat.tsx b/src/components/chat/Chat.tsx index ed66ecf..07be644 100644 --- a/src/components/chat/Chat.tsx +++ b/src/components/chat/Chat.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react'; +import { useState } from 'react'; import ChatButton from '@/components/chat/ChatButton'; import ChatDetail from '@/components/chat/ChatDetail'; @@ -44,7 +44,7 @@ const Chat = ({ const seller: SellerInfo = { sellerId: sellerId, shopName: sellerName }; const product: ProductInfo = { productId: productId, productName: productName }; const [user, setUser] = useState({ userId: userId, userName: userName }); - const [isCustomRoomId, setIsCustomRoomId] = useState(true); + const [isNowChatRoom, setIsNowChatRoom] = useState(false); const isSeller = isUser; const role = isSeller ? 'seller' : 'user'; @@ -65,20 +65,19 @@ const Chat = ({ return customRoomId; } - /** clickPrevButton() : 채팅방에서 뒤로가기 버튼 누르면 - * 1. 분기처리를 위해 customRoomId값을 빈 스트링을 넣는다. */ + /** clickPrevButton() : 채팅방에서 뒤로가기 버튼 */ const clickPrevButton = () => { - setCustomRoomId(''); + setIsNowChatRoom((prev) => !prev); }; /** clickListBox() : 채팅list에서 해당 채팅방으로 들어가기 위해 - * 1. isCustomRoomId를 false, + * 1. isNowChatRoom를 false, * 2. ChatBody.tsx에서 custumroomId를 받아와서 ChatList.tsx로 넘겨줌. * 3. seller일때 현재 디테일에서 넘어오는 userId, userName값은 판매자의 정보여서 ChatList.tsx에서 문의한 구매자의 userId값, userName값을 가져옴. */ const clickListBox = (customRoomId: string, userId: number, userName: string) => { - setIsCustomRoomId((prev) => !prev); + setIsNowChatRoom((prev) => !prev); setCustomRoomId(customRoomId); setUser({ ...user, userId, userName }); }; @@ -87,18 +86,12 @@ const Chat = ({ setIsModalOpen((prev) => !prev); }; - useEffect(() => { - if (customRoomId.length === 0) { - setIsCustomRoomId((prev) => !prev); - } - }, [customRoomId]); - return ( <> {isModalOpen && isSeller && ( - {isCustomRoomId ? ( + {!isNowChatRoom ? ( - {!isCustomRoomId ? ( + {isNowChatRoom ? ( Date: Fri, 3 Nov 2023 00:03:19 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat:#226=20sse=20=EC=BB=A4=EC=8A=A4?= =?UTF-8?q?=ED=85=80=ED=9B=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useSSE.ts | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/src/hooks/useSSE.ts b/src/hooks/useSSE.ts index c943921..af9c52d 100644 --- a/src/hooks/useSSE.ts +++ b/src/hooks/useSSE.ts @@ -9,22 +9,38 @@ type chatAlarm = { sender: string; }; -export const useSSE = (customRoomId: string, role: string) => { - console.log('useSSE', customRoomId); - console.log('role', role); - const [message, setMessage] = useState([]); +export const useSSE = (role: string, sellerId: number, userId: number) => { + const [eventSource, setEventSource] = useState( + new EventSource(`${import.meta.env.VITE_API_SSE_URL}/chat-alarm/${role}/${sellerId}`), + ); + const [message, setMessage] = useState(); - console.log(message); + console.log('useSSE', message); + console.log('role', role); + console.log('sellerId', sellerId); + console.log('userId', userId); useEffect(() => { - const eventSource = new EventSource( - `${import.meta.env.VITE_API_SSE_URL}/chat-alarm/${role}/${customRoomId}`, - ); - + if (role === 'user') { + setEventSource( + new EventSource( + `${import.meta.env.VITE_API_SSE_URL}/chat-alarm/${role}/${sellerId}/${userId}`, + ), + ); + } else { + setEventSource( + new EventSource(`${import.meta.env.VITE_API_SSE_URL}/chat-alarm/${role}/${sellerId}`), + ); + } + + console.log('start'); + console.log('eventSource', eventSource); + + if (!eventSource) return; eventSource.addEventListener('sse', function (event) { const message = JSON.parse(event.data); console.log('새로운 채팅 알람: ', message); - setMessage((prevMessages) => [...prevMessages, message]); + setMessage({ ...message }); }); eventSource.onerror = function (error) { @@ -38,12 +54,7 @@ export const useSSE = (customRoomId: string, role: string) => { console.log('EventSource closed'); } }); - - return () => { - eventSource.close(); - console.log('EventSource closed'); - }; - }, [customRoomId, role]); + }, [sellerId, role]); return message; }; From 8296f4aa5ee8d3e672f3fa9574b81e7216d5ab98 Mon Sep 17 00:00:00 2001 From: whtnqls124578 Date: Fri, 15 Dec 2023 20:01:54 +0900 Subject: [PATCH 4/6] =?UTF-8?q?feat:=EC=B1=84=ED=8C=85=EB=A6=AC=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20sse=20=EC=BB=A4=EC=8A=A4=ED=85=80=ED=9B=85=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/chat/Chat.tsx | 6 ++-- src/components/chat/ChatList.tsx | 13 ++++--- src/hooks/useSSE.ts | 62 ++++++++++++-------------------- 3 files changed, 33 insertions(+), 48 deletions(-) diff --git a/src/components/chat/Chat.tsx b/src/components/chat/Chat.tsx index 07be644..a8fc74c 100644 --- a/src/components/chat/Chat.tsx +++ b/src/components/chat/Chat.tsx @@ -71,7 +71,7 @@ const Chat = ({ }; /** clickListBox() : 채팅list에서 해당 채팅방으로 들어가기 위해 - * 1. isNowChatRoom를 false, + * 1. isNowChatRoom로 분기처리, * 2. ChatBody.tsx에서 custumroomId를 받아와서 ChatList.tsx로 넘겨줌. * 3. seller일때 현재 디테일에서 넘어오는 userId, userName값은 판매자의 정보여서 ChatList.tsx에서 문의한 구매자의 userId값, userName값을 가져옴. @@ -93,10 +93,10 @@ const Chat = ({ {!isNowChatRoom ? ( {isNowChatRoom ? ( { const [list, setList] = useState([]); const [shopImg, setShopImg] = useState(''); - const message = useSSE(customRoomId, role); + const message = useSSE(role, seller.sellerId, user.userId); + console.log('chatListMessage', message); - console.log(message); + // useEffect(() => { + // setList([...message]); + // }, []); const loadUserChatList: () => Promise = async () => { const sellerId = seller.sellerId; diff --git a/src/hooks/useSSE.ts b/src/hooks/useSSE.ts index af9c52d..534d0f8 100644 --- a/src/hooks/useSSE.ts +++ b/src/hooks/useSSE.ts @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react'; +import { useState } from 'react'; type chatAlarm = { content: string; @@ -10,51 +10,33 @@ type chatAlarm = { }; export const useSSE = (role: string, sellerId: number, userId: number) => { - const [eventSource, setEventSource] = useState( - new EventSource(`${import.meta.env.VITE_API_SSE_URL}/chat-alarm/${role}/${sellerId}`), - ); const [message, setMessage] = useState(); - console.log('useSSE', message); - console.log('role', role); - console.log('sellerId', sellerId); - console.log('userId', userId); - - useEffect(() => { - if (role === 'user') { - setEventSource( - new EventSource( - `${import.meta.env.VITE_API_SSE_URL}/chat-alarm/${role}/${sellerId}/${userId}`, - ), - ); - } else { - setEventSource( - new EventSource(`${import.meta.env.VITE_API_SSE_URL}/chat-alarm/${role}/${sellerId}`), - ); - } + const isUser = + role === 'user' + ? `${import.meta.env.VITE_API_SSE_URL}/chat-alarm/${role}/${sellerId}/${userId}` + : `${import.meta.env.VITE_API_SSE_URL}/chat-alarm/${role}/${sellerId}`; + + const eventSource = new EventSource(isUser); + console.log('EventSource opened'); - console.log('start'); - console.log('eventSource', eventSource); + eventSource.addEventListener('sse', function (event) { + const message = JSON.parse(event.data); + console.log('새로운 채팅 알람: ', message); + setMessage({ ...message }); + }); - if (!eventSource) return; - eventSource.addEventListener('sse', function (event) { - const message = JSON.parse(event.data); - console.log('새로운 채팅 알람: ', message); - setMessage({ ...message }); - }); + eventSource.onerror = function (error) { + console.error('EventSource failed:', error); + eventSource.close(); + }; - eventSource.onerror = function (error) { - console.error('EventSource failed:', error); + window.addEventListener('unload', function () { + if (eventSource) { eventSource.close(); - }; - - window.addEventListener('unload', function () { - if (eventSource) { - eventSource.close(); - console.log('EventSource closed'); - } - }); - }, [sellerId, role]); + console.log('EventSource closed'); + } + }); return message; }; From b7e77e1807b93bbbb44ce95d55d0925a34741948 Mon Sep 17 00:00:00 2001 From: whtnqls124578 Date: Sun, 17 Dec 2023 16:27:36 +0900 Subject: [PATCH 5/6] =?UTF-8?q?feat:useSSE=EC=97=90=EC=84=9C=20=EB=B0=9B?= =?UTF-8?q?=EC=9D=80=20message=EA=B0=92=EC=9C=BC=EB=A1=9C=ED=95=B4?= =?UTF-8?q?=EB=8B=B9=20chatbox=EC=97=90=20=20=EC=8B=A4=EC=8B=9C=EA=B0=84?= =?UTF-8?q?=20=EB=B0=98=EC=98=81=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/chat/ChatList.tsx | 22 +++++------- src/components/chat/chatList/ChatBody.tsx | 10 ++++-- src/hooks/useSSE.ts | 43 ++++++++++++----------- 3 files changed, 40 insertions(+), 35 deletions(-) diff --git a/src/components/chat/ChatList.tsx b/src/components/chat/ChatList.tsx index 1fda6ca..dc097da 100644 --- a/src/components/chat/ChatList.tsx +++ b/src/components/chat/ChatList.tsx @@ -24,7 +24,7 @@ export type List = { lastChat: Message; }; -type chatProps = { +type ChatProps = { clickListBox: (customRoomId: string, userId: number, userName: string) => void; handleOpen: () => void; seller: { @@ -48,23 +48,18 @@ const ChatList = ({ isSeller, product, role, -}: chatProps) => { +}: ChatProps) => { const [list, setList] = useState([]); - const [shopImg, setShopImg] = useState(''); const message = useSSE(role, seller.sellerId, user.userId); - console.log('chatListMessage', message); - - // useEffect(() => { - // setList([...message]); - // }, []); + //TODO: 리액트쿼리로 변경하기 const loadUserChatList: () => Promise = async () => { - const sellerId = seller.sellerId; - userChatList(sellerId) + userChatList(seller.sellerId) .then((resData) => { const data = resData.chatList; + console.log('list', data); const img = resData.shopImage; setList([...data]); setShopImg(img); @@ -80,6 +75,7 @@ const ChatList = ({ sellerChatList(sellerId, productId) .then((resData) => { const data = resData.chatList; + console.log('list', data); const img = resData.shopImage; setList([...data]); setShopImg(img); @@ -95,10 +91,10 @@ const ChatList = ({ }, [isSeller]); return ( -
+ <> - -
+ + ); }; diff --git a/src/components/chat/chatList/ChatBody.tsx b/src/components/chat/chatList/ChatBody.tsx index afe0aea..e75beed 100644 --- a/src/components/chat/chatList/ChatBody.tsx +++ b/src/components/chat/chatList/ChatBody.tsx @@ -1,13 +1,15 @@ import { List } from '@/components/chat/ChatList'; import ChatBox from '@/components/chat/chatList/ChatBox'; +import { ChatAlarm } from '@/hooks/useSSE'; import * as S from '../Chat.styles'; type ChatBodyProps = { chatList: List[]; clickListBox: (customRoomId: string, userId: number, userName: string) => void; + newMessage?: ChatAlarm; }; -const ChatBody = ({ chatList, clickListBox }: ChatBodyProps) => { +const ChatBody = ({ chatList, clickListBox, newMessage }: ChatBodyProps) => { return ( {chatList?.map((item, idx) => { @@ -17,7 +19,11 @@ const ChatBody = ({ chatList, clickListBox }: ChatBodyProps) => { key={idx} > { - const [message, setMessage] = useState(); + const [message, setMessage] = useState(); const isUser = role === 'user' ? `${import.meta.env.VITE_API_SSE_URL}/chat-alarm/${role}/${sellerId}/${userId}` : `${import.meta.env.VITE_API_SSE_URL}/chat-alarm/${role}/${sellerId}`; - const eventSource = new EventSource(isUser); - console.log('EventSource opened'); + const [eventSource] = useState(() => new EventSource(isUser)); - eventSource.addEventListener('sse', function (event) { - const message = JSON.parse(event.data); - console.log('새로운 채팅 알람: ', message); - setMessage({ ...message }); - }); + useEffect(() => { + console.log('되나', eventSource); + eventSource.addEventListener('sse', function (event) { + const message = JSON.parse(event.data); + console.log('새로운 채팅 알람: ', message); + setMessage({ ...message }); + }); - eventSource.onerror = function (error) { - console.error('EventSource failed:', error); - eventSource.close(); - }; - - window.addEventListener('unload', function () { - if (eventSource) { + eventSource.onerror = function (error) { + console.error('EventSource failed:', error); eventSource.close(); - console.log('EventSource closed'); - } - }); + }; + + window.addEventListener('unload', function () { + if (eventSource) { + eventSource.close(); + console.log('EventSource closed'); + } + }); + }, []); return message; }; From e77a3dbb41e5fb9578ea0afa3824eea213305f64 Mon Sep 17 00:00:00 2001 From: whtnqls124578 Date: Mon, 18 Dec 2023 00:25:56 +0900 Subject: [PATCH 6/6] =?UTF-8?q?bug:=EC=B1=84=ED=8C=85=EC=B0=BD=EC=9D=84=20?= =?UTF-8?q?=EB=81=88=ED=9B=84=20=EB=8B=A4=EC=8B=9C=20=EC=BC=B0=EC=9D=84?= =?UTF-8?q?=EB=95=8C=20=EC=9C=A0=EC=A0=80/=EC=85=80=EB=9F=AC=EC=9D=98=20?= =?UTF-8?q?=EC=B4=88=EA=B8=B0=EC=B0=BD=20=EC=95=88=EC=BC=9C=EC=A7=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/chat/Chat.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/chat/Chat.tsx b/src/components/chat/Chat.tsx index a8fc74c..0ac4cd9 100644 --- a/src/components/chat/Chat.tsx +++ b/src/components/chat/Chat.tsx @@ -41,6 +41,7 @@ const Chat = ({ isUser, shopImageUrl, }: ChatProps) => { + // TODO: 커스텀 훅으로 빼기. const seller: SellerInfo = { sellerId: sellerId, shopName: sellerName }; const product: ProductInfo = { productId: productId, productName: productName }; const [user, setUser] = useState({ userId: userId, userName: userName }); @@ -84,8 +85,11 @@ const Chat = ({ const handleOpen = () => { setIsModalOpen((prev) => !prev); + setIsNowChatRoom(false); }; + console.log('isNowChatRoom', isNowChatRoom); + return ( <>