diff --git a/src/components/Common/GameListCarousel/GameListCarousel.tsx b/src/components/Common/GameListCarousel/GameListCarousel.tsx index 4180e603..ffd40814 100644 --- a/src/components/Common/GameListCarousel/GameListCarousel.tsx +++ b/src/components/Common/GameListCarousel/GameListCarousel.tsx @@ -13,11 +13,13 @@ import { GameListCard, } from '@/components'; import { PATH } from '@/constants/router'; +import { SOCKET } from '@/constants/websocket'; import { useToast } from '@/hooks/useToast'; import { cn } from '@/lib/utils'; import { createRoom } from '@/services/rooms'; import useModalStore from '@/store/useModalStore'; import useRoomStore from '@/store/useRoomStore'; +import useSocketStore from '@/store/useSocketStore'; import { GameResponse } from '@/types/api'; interface GameListCarouselProps { @@ -29,8 +31,9 @@ const GameListCarousel = ({ games }: GameListCarouselProps) => { const router = useRouter(); const { toast } = useToast(); - const { setRoomId, setGameId } = useRoomStore(); + const { setRoomId } = useRoomStore(); const { closeModal } = useModalStore(); + const { sendMessage } = useSocketStore(); const [clickedGameId, setClickedGameId] = useState(null); @@ -63,7 +66,16 @@ const GameListCarousel = ({ games }: GameListCarouselProps) => { const handleChangeGame = (gameId: string) => { if (clickedGameId) return; setClickedGameId(gameId); - setGameId(gameId); + + if (sendMessage) { + sendMessage({ + destination: `${SOCKET.ROOM.CHANGE_GAME}`, + body: { + gameId, + }, + }); + } + closeModal(); }; diff --git a/src/components/Common/GameRoom/GameRoomController.tsx b/src/components/Common/GameRoom/GameRoomController.tsx index e0739a0c..c617e906 100644 --- a/src/components/Common/GameRoom/GameRoomController.tsx +++ b/src/components/Common/GameRoom/GameRoomController.tsx @@ -7,11 +7,11 @@ import { useEffect } from 'react'; import { Spinner } from '@/components'; import { PATH } from '@/constants/router'; -import { SOCKET } from '@/constants/websocket'; import { useFetchRoomDetail } from '@/hooks/queries'; import { useToast } from '@/hooks/useToast'; import { EnterRoomProps } from '@/hooks/useWebSocket'; import useRoomStore from '@/store/useRoomStore'; +import useSocketStore from '@/store/useSocketStore'; import { ChatMessage } from '@/types'; import GameRoomView from './GameRoomView'; @@ -37,7 +37,8 @@ const GameRoomController = ({ const { data: roomDetail, isError } = useFetchRoomDetail(roomId); - const { myName, setHostName, gameId } = useRoomStore(); + const { myName, setHostName } = useRoomStore(); + const { setSendMessage } = useSocketStore(); const isRoomManager = roomDetail.players.some( (player) => player.name === myName && player.isHost @@ -45,6 +46,12 @@ const GameRoomController = ({ const isSelfInPlayers = roomDetail.players.findIndex((user) => user.name === myName) !== -1; + useEffect(() => { + if (sendMessage) { + setSendMessage(sendMessage); + } + }, [sendMessage]); + useEffect(() => { if (roomDetail.players.length > 0) { const host = roomDetail.players.find((player) => player.isHost); @@ -52,7 +59,7 @@ const GameRoomController = ({ setHostName(host.name); } } - }, [roomDetail.players, setHostName]); + }, [roomDetail.players]); useEffect(() => { if (roomDetail && !isSelfInPlayers) { @@ -69,24 +76,6 @@ const GameRoomController = ({ } }, [myName, roomDetail]); - useEffect(() => { - sendMessage({ - destination: `${SOCKET.ROOM.CHANGE_PLAYER_NAME}`, - body: { - name: myName, - }, - }); - }, [myName]); - - useEffect(() => { - sendMessage({ - destination: `${SOCKET.ROOM.CHANGE_GAME}`, - body: { - gameId, - }, - }); - }, [gameId]); - if (!isSelfInPlayers) { return ; } diff --git a/src/components/ModalList/CreateUserNameModal.tsx b/src/components/ModalList/CreateUserNameModal.tsx index 63fbccb4..ea565b2b 100644 --- a/src/components/ModalList/CreateUserNameModal.tsx +++ b/src/components/ModalList/CreateUserNameModal.tsx @@ -15,15 +15,18 @@ import { ModalShell, } from '@/components'; import { STORAGE_KEY } from '@/constants/storage'; +import { SOCKET } from '@/constants/websocket'; import { useLocalStorage } from '@/hooks/useLocalStorage'; import { useToast } from '@/hooks/useToast'; import useModalStore from '@/store/useModalStore'; import useRoomStore from '@/store/useRoomStore'; +import useSocketStore from '@/store/useSocketStore'; const CreateUserNameModal = () => { const { closeModal } = useModalStore(); const { setItem } = useLocalStorage(); const { myName, setMyName } = useRoomStore(); + const { sendMessage } = useSocketStore(); const { toast } = useToast(); const formSchema = z.object({ @@ -52,13 +55,24 @@ const CreateUserNameModal = () => { description: '기존 닉네임과 다른 닉네임을 입력해주세요.', }); } else { + setMyName(values.username); + setItem(STORAGE_KEY.NICKNAME, values.username); + + if (sendMessage) { + sendMessage({ + destination: `${SOCKET.ROOM.CHANGE_PLAYER_NAME}`, + body: { + name: values.username, + }, + }); + } + toast({ variant: 'success', title: '닉네임 변경 성공', description: `${values.username}님, 그루파이별에 오신 것을 환영해요!`, }); - setMyName(values.username); - setItem(STORAGE_KEY.NICKNAME, values.username); + closeModal(); } }; diff --git a/src/hooks/useWebSocket.ts b/src/hooks/useWebSocket.ts index fc3683ec..1f7d1536 100644 --- a/src/hooks/useWebSocket.ts +++ b/src/hooks/useWebSocket.ts @@ -4,7 +4,7 @@ import * as StompJS from '@stomp/stompjs'; import { useQueryClient } from '@tanstack/react-query'; import { useRouter } from 'next/navigation'; -import { useRef, useState } from 'react'; +import { useCallback, useRef, useState } from 'react'; import { DEFAULT_ERROR_MESSAGE, ERROR_MESSAGE } from '@/constants/error'; import { QUERYKEY } from '@/constants/querykey'; @@ -109,22 +109,23 @@ export function useWebSocket() { client.current = null; }; - const sendMessage = ( - params: Omit & { body?: T } - ) => { - if (!client.current || !client.current.connected) { - return; - } + const sendMessage = useCallback( + (params: Omit & { body?: T }) => { + if (!client.current || !client.current.connected) { + return; + } - const { destination, body } = params; - const text = JSON.stringify(body); + const { destination, body } = params; + const text = JSON.stringify(body); - client.current?.publish({ - ...params, - destination: `${SOCKET.PUBLICATION}${destination}`, - body: text, - }); - }; + client.current?.publish({ + ...params, + destination: `${SOCKET.PUBLICATION}${destination}`, + body: text, + }); + }, + [] + ); const receiveMessage = (message: string) => { const { type, sender, content } = JSON.parse(message); diff --git a/src/store/useBalanceGameStore.ts b/src/store/useBalanceGameStore.ts index 66c9e662..e268adfd 100644 --- a/src/store/useBalanceGameStore.ts +++ b/src/store/useBalanceGameStore.ts @@ -6,7 +6,6 @@ interface BalanceGameStoreProps { round: BalanceGameRoundResponse; selectedPlayers: string[]; setRound: (round: BalanceGameRoundResponse) => void; - setTotalRounds: (count: number) => void; // @TODO: 추후에 완전 삭제 필요 addSelectedPlayers: (player: string) => void; resetSelectedPlayers: () => void; } @@ -20,20 +19,11 @@ const useBalanceGameStore = create((set) => ({ currentRound: 0, playSeconds: 0, }, - selectedPlayers: [], setRound: (round: BalanceGameRoundResponse) => set({ round, }), - - setTotalRounds: (count) => - set((state) => ({ - round: { - ...state.round, - totalRounds: count, - }, - })), addSelectedPlayers: (player) => set((state) => ({ selectedPlayers: [...state.selectedPlayers, player], diff --git a/src/store/useQnaGameStore.ts b/src/store/useQnaGameStore.ts index 8f6020d1..8b21d404 100644 --- a/src/store/useQnaGameStore.ts +++ b/src/store/useQnaGameStore.ts @@ -6,7 +6,6 @@ interface BalanceGameStoreProps { round: QnaGameRoundResponse; submittedPlayers: string[]; setRound: (round: QnaGameRoundResponse) => void; - setTotalRounds: (count: number) => void; // @TODO: 추후에 완전 삭제 필요 addSubmittedPlayer: (playerId: string) => void; clearSubmittedPlayers: () => void; reset: () => void; @@ -23,13 +22,6 @@ const useQnaGameStore = create((set) => ({ set({ round, }), - setTotalRounds: (count) => - set((state) => ({ - round: { - ...state.round, - totalRounds: count, - }, - })), addSubmittedPlayer: (playerId) => set((state) => ({ submittedPlayers: [...state.submittedPlayers, playerId], diff --git a/src/store/useRoomStore.ts b/src/store/useRoomStore.ts index 3ff75511..ce1b696d 100644 --- a/src/store/useRoomStore.ts +++ b/src/store/useRoomStore.ts @@ -11,7 +11,6 @@ interface RoomStoreProps { myName: string; setRoomStatus: (status: roomStatusType) => void; setRoomId: (id: string) => void; - setGameId: (id: string) => void; setHostName: (name: string) => void; setMyName: (name: string) => void; getHostName: () => string | null; @@ -26,7 +25,6 @@ const useRoomStore = create((set, get) => ({ myName: '', setRoomStatus: (status) => set({ roomStatus: status }), setRoomId: (id) => set({ roomId: id }), - setGameId: (id) => set({ gameId: id }), setHostName: (name) => set({ hostName: name }), setMyName: (name) => set({ myName: name }), getHostName: () => get().hostName, diff --git a/src/store/useSocketStore.ts b/src/store/useSocketStore.ts new file mode 100644 index 00000000..1b21273a --- /dev/null +++ b/src/store/useSocketStore.ts @@ -0,0 +1,22 @@ +import * as StompJS from '@stomp/stompjs'; +import { create } from 'zustand'; + +interface SocketStoreProps { + sendMessage: + | ((params: Omit & { body?: T }) => void) + | null; + setSendMessage: ( + sendFn: + | (( + params: Omit & { body?: T } + ) => void) + | null + ) => void; +} + +const useSocketStore = create((set) => ({ + sendMessage: null, + setSendMessage: (sendFn) => set({ sendMessage: sendFn }), +})); + +export default useSocketStore;