Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

297 refactor roomcontext zustand move #303

Open
wants to merge 4 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"tanstack",
"toastify",
"typeorm",
"Xmark"
"Xmark",
"zustand"
]
}
38 changes: 37 additions & 1 deletion client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"react-router-dom": "^6.18.0",
"react-textarea-autosize": "^8.5.3",
"react-toastify": "^9.1.3",
"socket.io-client": "^4.7.2"
"socket.io-client": "^4.7.2",
"zustand": "^4.5.2"
},
"devDependencies": {
"@types/react": "^18.2.15",
Expand Down
37 changes: 10 additions & 27 deletions client/src/contexts/RoomProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,16 @@
import { ReactNode, createContext, useEffect, useRef, useState } from 'react';
import { ReactNode, createContext, useEffect, useRef } from 'react';
import { Socket, io } from 'socket.io-client';
import { MessageInterface } from '../types/Message';
import { RoomInfoType } from '../types/RoomInfoType';
import { ProblemType } from '../types/ProblemType';
import { useLocation, useParams } from 'react-router-dom';
import { useRoomStore } from '../store/roomStore';
import { useLocation } from 'react-router-dom';

export type RoomContextType = {
isHost: boolean;
roomCode: string;
roomId: string | undefined;
inputRef: React.RefObject<HTMLTextAreaElement>;
messagesRef: React.RefObject<HTMLUListElement>;
socketRef: React.RefObject<Socket | null>;
messages: MessageInterface[];
setMessages: React.Dispatch<React.SetStateAction<MessageInterface[]>>;
roomInfo: RoomInfoType;
setRoomInfo: React.Dispatch<React.SetStateAction<RoomInfoType>>;
problems: ProblemType[];
setProblems: React.Dispatch<React.SetStateAction<ProblemType[]>>;
duration: number;
setDuration: React.Dispatch<React.SetStateAction<number>>;
};

export const RoomContext = createContext<RoomContextType>(
Expand All @@ -32,24 +23,25 @@ interface RoomProviderProps {

export const RoomProvider: React.FC<RoomProviderProps> = ({ children }) => {
const serverUrl = import.meta.env.VITE_BASE_URL;
const { setRoomInfo, setProblems, roomId } = useRoomStore();

const location = useLocation();

const isHost = location.state?.isHost;
const roomCode = location.state?.roomCode;
const roomId = useParams<{ roomId: string }>().roomId;
// const roomId = useParams<{ roomId: string }>().roomId;

const inputRef = useRef<HTMLTextAreaElement>(null);
const messagesRef = useRef<HTMLUListElement>(null);
const socketRef = useRef<Socket | null>(null);

const [messages, setMessages] = useState<MessageInterface[]>([]);
// const [messages, setMessages] = useState<MessageInterface[]>([]);

const [roomInfo, setRoomInfo] = useState<RoomInfoType>({} as RoomInfoType);
// const [roomInfo, setRoomInfo] = useState<RoomInfoType>({} as RoomInfoType);

const [problems, setProblems] = useState<ProblemType[]>([]);
// const [problems, setProblems] = useState<ProblemType[]>([]);

const [duration, setDuration] = useState<number>(0); // minutes
// const [duration, setDuration] = useState<number>(0); // minutes

useEffect(() => {
const socket: Socket = io(serverUrl, {
Expand All @@ -74,25 +66,16 @@ export const RoomProvider: React.FC<RoomProviderProps> = ({ children }) => {
return () => {
socket.disconnect();
};
}, [roomId, serverUrl]);
}, [roomId, serverUrl, setProblems, setRoomInfo]);

return (
<RoomContext.Provider
value={{
isHost,
roomCode,
roomId,
inputRef,
messagesRef,
socketRef,
messages,
setMessages,
roomInfo,
setRoomInfo,
problems,
setProblems,
duration,
setDuration,
}}>
{children}
</RoomContext.Provider>
Expand Down
8 changes: 5 additions & 3 deletions client/src/pages/Room/Chat/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ import {
} from '../../../types/Message';
import { useRoom } from '../../../hooks/useRoom';
import { useEffect } from 'react';
import { useRoomStore } from '../../../store/roomStore';

export default function Chat() {
const { user } = useAuthContext();
const { roomId, messages, setMessages, inputRef, messagesRef, socketRef } =
const {roomId, messages, setMessages} = useRoomStore();
const { inputRef, messagesRef, socketRef } =
useRoom();

const socket = socketRef.current;
Expand Down Expand Up @@ -80,8 +82,8 @@ export default function Chat() {
}

socket?.on('chat-message', (newMessage) => {
setMessages((prevMessages) => {
const newMessages = [...prevMessages, newMessage];
setMessages((prevMessages: MessageInterface[]) => {
const newMessages: MessageInterface[] = [...prevMessages, newMessage];
setLocalStorageItem(
`${roomId}-messages`,
JSON.stringify({
Expand Down
4 changes: 2 additions & 2 deletions client/src/pages/Room/Chat/Message.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { useRoom } from '../../../hooks/useRoom';
import { userColors } from '../../../../public/userColors';
import { hash } from '../../../utils/hash';
import { ChatEvent, MessageInterface } from '../../../types/Message';
import MessageBody from './MessageBody';
import { useRoomStore } from '../../../store/roomStore';

export default function Message({ message }: { message: MessageInterface }) {
const { roomCode } = useRoom();
const { roomCode } = useRoomStore();
const generateRandomColor = (username: string) => {
const idx = Math.abs(hash(username + roomCode) % userColors.length);
return userColors[idx];
Expand Down
11 changes: 4 additions & 7 deletions client/src/pages/Room/Problems/Problems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import { FaPencil } from 'react-icons/fa6';

import RoomSettingModal from './RoomSettingModal/RoomSettingModal';
import { useTheme } from '../../../hooks/useTheme';
import { useRoom } from '../../../hooks/useRoom';
import ProblemLists from './ProblemLists';
import { useRoomStore } from '../../../store/roomStore';
import { useRoom } from '../../../hooks/useRoom';

export default function Problems() {
const { isHost, roomInfo, problems, setProblems, duration, setDuration } =
useRoom();
const { isHost } = useRoom();
const {roomInfo, problems } = useRoomStore();
const { theme } = useTheme();

const [isModalOpen, setIsModalOpen] = useState(false);
Expand Down Expand Up @@ -57,10 +58,6 @@ export default function Problems() {
modalOverlayRef={modalOverlayRef}
closeModal={closeModal}
modalOutsideClick={modalOutsideClick}
problems={problems}
setProblems={setProblems}
duration={duration}
setDuration={setDuration}
/>
)}
</>
Expand Down
4 changes: 2 additions & 2 deletions client/src/pages/Room/Problems/RoomSettingModal/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export interface DropdownProps<T> {
options: Array<T>;
optionPostFix?: string;
selected: T;
setSelected: React.Dispatch<React.SetStateAction<T>>;
setSelected: (value: T) => void | React.Dispatch<React.SetStateAction<T>>;
buttonClassName?: string;
itemBoxClassName?: string;
itemClassName?: string;
Expand All @@ -17,7 +17,7 @@ export interface DropdownProps<T> {
* @param {Array<T>} props.options dropdown items with value
* @param {string} props.optionPostFix postfix of dropdown item
* @param {T} props.selected selected item
* @param {React.Dispatch<React.SetStateAction<T>>} props.setSelected set selected item
* @param {function(T):void | React.Dispatch<React.SetStateAction<T>> } props.setSelected set selected item
* @param {string} props.buttonClassName className of dropdown button for tailwindcss
* @param {string} props.itemBoxClassName className of dropdown item box for tailwindcss
* @param {string} props.itemClassName className of dropdown item for tailwindcss
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
import { RefObject, useState, Dispatch, SetStateAction } from 'react';
import { useState, RefObject } from 'react';
import { FaXmark } from 'react-icons/fa6';
import { FaToggleOff } from 'react-icons/fa6';
import { FaToggleOn } from 'react-icons/fa6';
import { useShallow } from 'zustand/react/shallow';

import SelectProblem from './SelectProblem';
import RandomProblem from './RandomProblem';
import ProblemList from './ProblemList';
import { FaXmark } from 'react-icons/fa6';
import { FaToggleOff } from 'react-icons/fa6';
import { FaToggleOn } from 'react-icons/fa6';
import Dropdown from './Dropdown';
import { ProblemType } from '../../../../types/ProblemType';
import { useRoomStore } from '../../../../store/roomStore';

interface RoomSettingModalProps {
modalOverlayRef: RefObject<HTMLDivElement>;
closeModal: () => void;
modalOutsideClick: (arg: React.MouseEvent<HTMLDivElement>) => void;
problems: ProblemType[];
setProblems: Dispatch<SetStateAction<ProblemType[]>>;
duration: number;
setDuration: Dispatch<SetStateAction<number>>;
}

const iconStyle = {
Expand All @@ -27,11 +25,15 @@ export default function RoomSettingModal({
modalOverlayRef,
closeModal,
modalOutsideClick,
problems,
setProblems,
duration,
setDuration,
}: RoomSettingModalProps) {
const { problems, setProblems, duration, setDuration } = useRoomStore(
useShallow((state) => ({
problems: state.problems,
setProblems: state.setProblems,
duration: state.duration,
setDuration: state.setDuration,
})),
);
Comment on lines +29 to +36
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분 뿐만 아니라, useRoomStore()를 사용하는 부분은 다 이렇게 바꿔줘야 하는 것 같아요.

const [problem, setProblem] = useState<ProblemType>({} as ProblemType);
const [problemList, setProblemList] = useState<ProblemType[]>(problems);
const [isRandom, setIsRandom] = useState<boolean>(false);
Expand Down
2 changes: 1 addition & 1 deletion client/src/pages/Room/Room.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Problems from './Problems/Problems';
import ScoreboardButton from './ScoreBoard/ScoreBoardButton';
import Chat from './Chat/Chat';
import StartButton from './Tiimer/StartButton';
import StartButton from './Timer/StartButton';
import RoomInfo from './RoomInfo/RoomInfo';

export default function Room() {
Expand Down
4 changes: 2 additions & 2 deletions client/src/pages/Room/RoomInfo/RoomInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import ExitButton from './ExitButton';
import { FaRegCopy } from 'react-icons/fa6';
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import { useRoom } from '../../../hooks/useRoom';
import { useRoomStore } from '../../../store/roomStore';

export default function RoomInfo() {
const { roomCode } = useRoom();
const { roomCode } = useRoomStore();
Copy link
Collaborator

@kiuuon kiuuon May 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이렇게 하나만 가져오는 경우에는
const roomCode = useRoomStore((state) => state.roomCode);
이렇게 쓰면 될 거 같습니다!


const copyToClipboard = () => {
navigator.clipboard.writeText(roomCode);
Expand Down
4 changes: 2 additions & 2 deletions client/src/pages/Room/ScoreBoard/ScoreBoard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useRoom } from '../../../hooks/useRoom';
import { useRoomStore } from '../../../store/roomStore';
import { ScoreBoardInformation } from '../../../types/ScoreBoardInformation';
import { Submission } from '../../../types/Submission';
import Players from './Players';
Expand All @@ -13,7 +13,7 @@ interface PlayerScore {
}

export default function ScoreBoard({ scores }: ScoreBoardProps) {
const { participantNames, problems } = useRoom().roomInfo;
const { participantNames, problems } = useRoomStore().roomInfo;

const playerNames: string[] = participantNames;
const problemIds: number[] = problems.map((problem) => problem.bojProblemId);
Expand Down
4 changes: 2 additions & 2 deletions client/src/pages/Room/ScoreBoard/ScoreBoardButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import { FaChartSimple } from 'react-icons/fa6';
import ScoreBoardModal from './ScoreBoardModal';
import { useRef, useState } from 'react';
import { getScoreBoardInformation } from '../../../apis/scoreBoard';
import { useRoom } from '../../../hooks/useRoom';
import { ScoreBoardInformation } from '../../../types/ScoreBoardInformation';
import { useRoomStore } from '../../../store/roomStore';

export default function ScoreboardButton() {
const [isModalOpen, setIsModalOpen] = useState(false);
const [scores, setScores] = useState<ScoreBoardInformation>({submissions: [], rankings: []});
const modalOverlayRef = useRef<HTMLDivElement>(null);
const { roomCode, roomInfo } = useRoom();
const { roomCode, roomInfo } = useRoomStore();

const openModal = async () => {
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useRoom } from '../../../hooks/useRoom';
import { useRoomStore } from '../../../store/roomStore';
import Timer from './Timer';

export type StartButtonProps = {
Expand All @@ -7,7 +8,8 @@ export type StartButtonProps = {
};

export default function StartButton() {
const { socketRef, isHost, roomInfo, problems, duration } = useRoom();
const { isHost, socketRef } = useRoom();
const { roomInfo, problems, duration } = useRoomStore();

const start = () => {
console.log('start');
Expand Down
21 changes: 21 additions & 0 deletions client/src/store/roomStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { create } from 'zustand';
import { RoomInfoType } from '../types/RoomInfoType';
import { ProblemType } from '../types/ProblemType';
import { RoomStoreType } from '../types/RoomStoreType';

export const useRoomStore = create<RoomStoreType>((set) => ({
roomId: '',
messages: [],
setMessages: (messages) =>
set((state) => ({
...state,
messages:
typeof messages === 'function' ? messages(state.messages) : messages,
})),
roomInfo: {} as RoomInfoType,
setRoomInfo: (roomInfo: RoomInfoType) => set({ roomInfo }),
problems: [],
setProblems: (problems: ProblemType[]) => set({ problems }),
duration: 0,
setDuration: (duration: number) => set({ duration }),
}));
Loading