diff --git a/src/container/myPage/chatPage/components/ChatRoom.tsx b/src/container/myPage/chatPage/components/ChatRoom.tsx index ef2b2497..89a7a3bd 100644 --- a/src/container/myPage/chatPage/components/ChatRoom.tsx +++ b/src/container/myPage/chatPage/components/ChatRoom.tsx @@ -9,9 +9,10 @@ import { userInfoType } from "../ChatPage"; import { useRoomInfoState } from "../../../../recoil/chat/roomInfoStateAtom"; import { deleteChatRoom } from "../../../../apis/controller/chatPage"; import { useForm } from "react-hook-form"; +import useChatWebsocket from "../../../../hooks/useChatWebsocket"; -type messageObjectType = { - roomId: number; +export type messageObjectType = { + chatRoomId: number; sender: string; message: string; messageType: "CHAT" | "RESERVEATION" | "REVIEW"; @@ -23,76 +24,24 @@ function ChatRoom({ userInfo }: { userInfo?: userInfoType }) { const [chatHistoryState, setChatHistoryState] = useState( [] ); + + const getChatHistoryState = (newChatHistoryState: messageObjectType[]) => { + setChatHistoryState(newChatHistoryState); + }; + const { getAccessToken } = useTokenService(); const clientRef = useRef({}); const { register, getValues, setValue, reset } = useForm(); - const connectHandler = () => { - if (window !== undefined) { - clientRef.current = new StompJs.Client({ - brokerURL: "wss://api.dessert-gallery.site/ws/chat/websocket", - debug: function (str) { - console.log(str); - }, - // webSocketFactory: () => { - // return new SockJS( - // "https://api.dessert-gallery.site/ws/chat" - // ) as WebSocket; - // }, - connectHeaders: { Authorization: getAccessToken() }, - reconnectDelay: 5000, //자동 재연결 - heartbeatIncoming: 4000, - heartbeatOutgoing: 4000, - }); - clientRef.current.onConnect = function (frame: any) { - clientRef.current.subscribe( - `/sub/${roomInfoState.roomId}`, - messageCheckHandler - ); - console.log("연결성공", frame); - }; - clientRef.current.onWebSocketError = (err: any) => { - console.log("웹소켓 에러"); - console.log(err); - }; - clientRef.current.onStompError = function (frame: any) { - console.log("브로커 에러: ", frame.headers["message"]); - console.log("추가 정보: " + frame.body); - }; - clientRef.current.activate(); - } - }; - - const messageHandler = (message: string) => { - clientRef.current.publish({ - destination: "/pub/chat", - // skipContentLengthHeader: true, - body: JSON.stringify({ - chatRoomId: roomInfoState.roomId, - message: message, - messageType: "CHAT", - sender: userInfo?.nickname, - }), - headers: { Authorization: getAccessToken() }, - }); - }; - - const messageReceiveHandler = (messageResponse: any) => { - const messageBody: messageObjectType = JSON.parse(messageResponse.body); - const { roomId, sender, message, messageType, dateTime } = messageBody; - const newChat = { - roomId, - sender, - message, - messageType, - dateTime, - }; - console.log(newChat); - - setChatHistoryState([...chatHistoryState, newChat]); - }; + const { + connectHandler, + messageHandler, + onClickReservation, + onClickReview, + disconnectHandler, + } = useChatWebsocket(chatHistoryState, getChatHistoryState, userInfo); const messageCheckHandler = async () => { if (roomInfoState.roomId !== 0) { @@ -103,35 +52,6 @@ function ChatRoom({ userInfo }: { userInfo?: userInfoType }) { } }; - const onClickReservation = () => { - clientRef.current.publish({ - destination: "/pub/chat", - // skipContentLengthHeader: true, - body: JSON.stringify({ - chatRoomId: roomInfoState.roomId, - message: `${"user"}님의 예약이 확정되었습니다.`, - messageType: "RESERVEATION", - sender: userInfo?.nickname, - }), - headers: { Authorization: getAccessToken() }, - }); - }; - - const onClickReview = () => { - clientRef.current.publish({ - destination: "/pub/chat", - // skipContentLengthHeader: true, - body: JSON.stringify({ - chatRoomId: roomInfoState.roomId, - message: `${"user"}님, 디저트는 잘 받으셨나요? - 만족하셨다면 후기를 작성해주세요`, - messageType: "REVIEW", - sender: userInfo?.nickname, - }), - headers: { Authorization: getAccessToken() }, - }); - }; - useEffect(() => { console.log(roomInfoState.roomId); console.log(roomInfoState); @@ -139,7 +59,7 @@ function ChatRoom({ userInfo }: { userInfo?: userInfoType }) { messageCheckHandler(); connectHandler(); return () => { - clientRef.current.deactivate(); + disconnectHandler(); }; }, [roomInfoState]); diff --git a/src/hooks/useChatWebsocket.ts b/src/hooks/useChatWebsocket.ts new file mode 100644 index 00000000..dcb8757f --- /dev/null +++ b/src/hooks/useChatWebsocket.ts @@ -0,0 +1,128 @@ +import { useEffect, useRef, useState } from "react"; +import { useTokenService } from "./useTokenService"; +import SockJS from "sockjs-client"; +import * as StompJs from "@stomp/stompjs"; +import { useRoomInfoState } from "../recoil/chat/roomInfoStateAtom"; +import { userInfoType } from "../container/myPage/chatPage/ChatPage"; +import { messageObjectType } from "../container/myPage/chatPage/components/ChatRoom"; + +const useChatWebsocket = ( + chatHistoryState: messageObjectType[], + getChatHistoryState: (newChat: messageObjectType[]) => void, + userInfo?: userInfoType +) => { + const [roomInfoState, setRoomInfoState] = useRoomInfoState(); + const { getAccessToken } = useTokenService(); + const clientRef = useRef({}); + + const connectHandler = () => { + if (window !== undefined) { + clientRef.current = new StompJs.Client({ + brokerURL: "wss://api.dessert-gallery.site/ws/chat/websocket", + debug: function (str) { + console.log(str); + }, + // webSocketFactory: () => { + // return new SockJS( + // "https://api.dessert-gallery.site/ws/chat" + // ) as WebSocket; + // }, + connectHeaders: { Authorization: getAccessToken() }, + reconnectDelay: 5000, //자동 재연결 + heartbeatIncoming: 4000, + heartbeatOutgoing: 4000, + }); + clientRef.current.onConnect = function (frame: any) { + clientRef.current.subscribe( + `/sub/${roomInfoState.roomId}`, + messageReceiveHandler + ); + console.log("연결성공", frame); + }; + clientRef.current.onWebSocketError = (err: any) => { + console.log("웹소켓 에러"); + console.log(err); + }; + clientRef.current.onStompError = function (frame: any) { + console.log("브로커 에러: ", frame.headers["message"]); + console.log("추가 정보: " + frame.body); + }; + clientRef.current.activate(); + } + }; + + const disconnectHandler = () => { + clientRef.current.deactivate(); + }; + + const messageHandler = (message: string) => { + clientRef.current.publish({ + destination: "/pub/chat", + body: JSON.stringify({ + chatRoomId: roomInfoState.roomId, + message: message, + messageType: "CHAT", + sender: userInfo?.nickname, + }), + headers: { Authorization: getAccessToken() }, + }); + }; + + const messageReceiveHandler = (messageResponse: any) => { + const messageBody: messageObjectType = JSON.parse(messageResponse.body); + console.log(messageResponse.body); + + const { chatRoomId, sender, message, messageType, dateTime } = messageBody; + const newChat = { + chatRoomId, + sender, + message, + messageType, + dateTime, + }; + console.log(newChat); + + console.log(chatHistoryState, newChat); + + getChatHistoryState([...chatHistoryState, newChat]); + }; + + const onClickReservation = () => { + clientRef.current.publish({ + destination: "/pub/chat", + // skipContentLengthHeader: true, + body: JSON.stringify({ + chatRoomId: roomInfoState.roomId, + message: `${"user"}님의 예약이 확정되었습니다.`, + messageType: "RESERVEATION", + sender: userInfo?.nickname, + }), + headers: { Authorization: getAccessToken() }, + }); + }; + + const onClickReview = () => { + clientRef.current.publish({ + destination: "/pub/chat", + // skipContentLengthHeader: true, + body: JSON.stringify({ + chatRoomId: roomInfoState.roomId, + message: `${"user"}님, 디저트는 잘 받으셨나요? + 만족하셨다면 후기를 작성해주세요`, + messageType: "REVIEW", + sender: userInfo?.nickname, + }), + headers: { Authorization: getAccessToken() }, + }); + }; + + return { + connectHandler, + messageHandler, + onClickReservation, + onClickReview, + disconnectHandler, + }; +}; + +export default useChatWebsocket;