From 357d382459c938dea2afc2d0f1b715edc64756ad Mon Sep 17 00:00:00 2001 From: "dongind.oct" Date: Wed, 5 Jun 2024 08:15:13 +0900 Subject: [PATCH 01/12] =?UTF-8?q?refactor=20:=20SocketContext=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit context로 socket을 전달하기 위한 SocketContext 생성 --- frontend/src/hooks/common/socket/useSocket.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/frontend/src/hooks/common/socket/useSocket.ts b/frontend/src/hooks/common/socket/useSocket.ts index 258d2ae..26ab78e 100644 --- a/frontend/src/hooks/common/socket/useSocket.ts +++ b/frontend/src/hooks/common/socket/useSocket.ts @@ -1,6 +1,6 @@ import { io } from "socket.io-client"; import { BASE_URL } from "../../../constants/path"; -import { useEffect, useState } from "react"; +import { createContext, useEffect, useState } from "react"; import { getAccessToken } from "../../../apis/utils/authAPI"; const useSocket = (projectId: string) => { @@ -13,6 +13,8 @@ const useSocket = (projectId: string) => { }); const [connected, setConnected] = useState(false); + const SocketContext = createContext(socket); + useEffect(() => { const handleOnConnect = () => { setConnected(true); @@ -30,7 +32,7 @@ const useSocket = (projectId: string) => { }; }, []); - return { socket, connected }; + return { socket, connected, SocketContext }; }; export default useSocket; From 2b465c2cf4e8ca45e8fd9afc6c722348fdb92a1f Mon Sep 17 00:00:00 2001 From: "dongind.oct" Date: Wed, 5 Jun 2024 22:57:14 +0900 Subject: [PATCH 02/12] =?UTF-8?q?refactor=20:=20useRouterContext=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - landing project컴포넌트에 useRouterContext를 시험 적용 --- .../landing/project/LandingProject.tsx | 68 ++++++++++++++----- frontend/src/hooks/common/socket/useSocket.ts | 6 +- frontend/src/pages/landing/LandingPage.tsx | 3 +- 3 files changed, 55 insertions(+), 22 deletions(-) diff --git a/frontend/src/components/landing/project/LandingProject.tsx b/frontend/src/components/landing/project/LandingProject.tsx index b807a6b..dc7bb31 100644 --- a/frontend/src/components/landing/project/LandingProject.tsx +++ b/frontend/src/components/landing/project/LandingProject.tsx @@ -1,27 +1,61 @@ -import { LandingProjectDTO } from "../../../types/DTO/landingDTO"; +import { Socket } from "socket.io-client"; +import { LandingDTO, LandingProjectDTO } from "../../../types/DTO/landingDTO"; import formatDate from "../../../utils/formatDate"; import LandingProjectLink from "./LandingProjectLink"; +import { useOutletContext } from "react-router-dom"; +import { useEffect, useState } from "react"; +import { DEFAULT_VALUE } from "../../../constants/landing"; +import { + LandingSocketData, + LandingSocketDomain, +} from "../../../types/common/landing"; interface LandingProjectProps { - project: LandingProjectDTO; + // project: LandingProjectDTO; projectId: string; } -const LandingProject = ({ project, projectId }: LandingProjectProps) => ( -
-
-

| {project.title}

-

- {project.createdAt && formatDate(project.createdAt)} -

-
-
{project.subject}
-
- - - +const LandingProject = ({ projectId }: LandingProjectProps) => { + const { socket }: { socket: Socket } = useOutletContext(); + const [project, setProject] = useState( + DEFAULT_VALUE.PROJECT + ); + + const handleInitEvent = (content: LandingDTO) => { + const { project } = content as LandingDTO; + setProject(project); + }; + + const handleOnLanding = ({ domain, action, content }: LandingSocketData) => { + if (domain !== LandingSocketDomain.INIT) return; + handleInitEvent(content); + }; + + useEffect(() => { + socket.emit("joinLanding"); + socket.on("landing", handleOnLanding); + + return () => { + socket.off("landing"); + }; + }, [socket]); + + return ( +
+
+

| {project.title}

+

+ {project.createdAt && formatDate(project.createdAt)} +

+
+
{project.subject}
+
+ + + +
-
-); + ); +}; export default LandingProject; diff --git a/frontend/src/hooks/common/socket/useSocket.ts b/frontend/src/hooks/common/socket/useSocket.ts index 26ab78e..258d2ae 100644 --- a/frontend/src/hooks/common/socket/useSocket.ts +++ b/frontend/src/hooks/common/socket/useSocket.ts @@ -1,6 +1,6 @@ import { io } from "socket.io-client"; import { BASE_URL } from "../../../constants/path"; -import { createContext, useEffect, useState } from "react"; +import { useEffect, useState } from "react"; import { getAccessToken } from "../../../apis/utils/authAPI"; const useSocket = (projectId: string) => { @@ -13,8 +13,6 @@ const useSocket = (projectId: string) => { }); const [connected, setConnected] = useState(false); - const SocketContext = createContext(socket); - useEffect(() => { const handleOnConnect = () => { setConnected(true); @@ -32,7 +30,7 @@ const useSocket = (projectId: string) => { }; }, []); - return { socket, connected, SocketContext }; + return { socket, connected }; }; export default useSocket; diff --git a/frontend/src/pages/landing/LandingPage.tsx b/frontend/src/pages/landing/LandingPage.tsx index 7ee73c9..749ef51 100644 --- a/frontend/src/pages/landing/LandingPage.tsx +++ b/frontend/src/pages/landing/LandingPage.tsx @@ -22,7 +22,8 @@ const LandingPage = () => { return (
- + {/* */} +
From c22348edf7824001b4206a89bbbd4cbc7b2a6f02 Mon Sep 17 00:00:00 2001 From: "dongind.oct" Date: Wed, 5 Jun 2024 23:30:19 +0900 Subject: [PATCH 03/12] =?UTF-8?q?refactor=20:=20LandingSprint=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=EC=97=90=20=EC=86=8C=EC=BC=93=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20=EC=A7=81=EC=A0=91=20=EC=A0=84=EB=8B=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - socket 객체를 직접 전달하는 구조를 LandingSprint에 구현 --- .../landing/project/LandingProject.tsx | 3 +- .../landing/sprint/LandingSprint.tsx | 29 +++++++++++++++++-- frontend/src/pages/landing/LandingPage.tsx | 5 ++-- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/landing/project/LandingProject.tsx b/frontend/src/components/landing/project/LandingProject.tsx index dc7bb31..3e3a98c 100644 --- a/frontend/src/components/landing/project/LandingProject.tsx +++ b/frontend/src/components/landing/project/LandingProject.tsx @@ -11,7 +11,6 @@ import { } from "../../../types/common/landing"; interface LandingProjectProps { - // project: LandingProjectDTO; projectId: string; } @@ -26,7 +25,7 @@ const LandingProject = ({ projectId }: LandingProjectProps) => { setProject(project); }; - const handleOnLanding = ({ domain, action, content }: LandingSocketData) => { + const handleOnLanding = ({ domain, content }: LandingSocketData) => { if (domain !== LandingSocketDomain.INIT) return; handleInitEvent(content); }; diff --git a/frontend/src/components/landing/sprint/LandingSprint.tsx b/frontend/src/components/landing/sprint/LandingSprint.tsx index 94bd03a..1d929ac 100644 --- a/frontend/src/components/landing/sprint/LandingSprint.tsx +++ b/frontend/src/components/landing/sprint/LandingSprint.tsx @@ -1,9 +1,34 @@ -import { LandingSprintDTO } from "../../../types/DTO/landingDTO"; +import { useEffect, useState } from "react"; +import { LandingDTO, LandingSprintDTO } from "../../../types/DTO/landingDTO"; import diffBetweenDate from "../../../utils/diffBetweenDate"; import formatDate from "../../../utils/formatDate"; import LandingSprintBar from "./LandingSprintBar"; +import { + LandingSocketData, + LandingSocketDomain, +} from "../../../types/common/landing"; +import { Socket } from "socket.io-client"; +import { useOutletContext } from "react-router-dom"; + +const LandingSprint = () => { + const { socket }: { socket: Socket } = useOutletContext(); + const [sprint, setSprint] = useState(null); + const handleInitEvent = (content: LandingDTO) => { + const { sprint } = content as LandingDTO; + setSprint(sprint); + }; + const handleOnLanding = ({ domain, content }: LandingSocketData) => { + if (domain !== LandingSocketDomain.INIT) return; + handleInitEvent(content); + }; + useEffect(() => { + socket.on("landing", handleOnLanding); + + return () => { + socket.off("landing"); + }; + }); -const LandingSprint = ({ sprint }: { sprint: LandingSprintDTO | null }) => { return (

| 스프린트 정보

diff --git a/frontend/src/pages/landing/LandingPage.tsx b/frontend/src/pages/landing/LandingPage.tsx index 749ef51..45e637a 100644 --- a/frontend/src/pages/landing/LandingPage.tsx +++ b/frontend/src/pages/landing/LandingPage.tsx @@ -15,19 +15,18 @@ const LandingPage = () => { } const { socket }: { socket: Socket } = useOutletContext(); - const { project, myInfo, member, sprint, link, memoList, inviteLinkIdRef } = + const { project, myInfo, member, link, memoList, inviteLinkIdRef } = useLandingSocket(socket); const { memoSocketEvent } = useLandingEmitEvent(socket); return (
- {/* */}
- + Date: Wed, 5 Jun 2024 23:49:10 +0900 Subject: [PATCH 04/12] =?UTF-8?q?refactor=20:=20Landing=20Link=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20Socket=20=EA=B0=9D=EC=B2=B4=20?= =?UTF-8?q?=EC=A7=81=EC=A0=91=20=EC=A3=BC=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/landing/link/LandingLink.tsx | 31 +++++++++++++++++-- frontend/src/pages/landing/LandingPage.tsx | 4 +-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/landing/link/LandingLink.tsx b/frontend/src/components/landing/link/LandingLink.tsx index 626021b..9aef1f2 100644 --- a/frontend/src/components/landing/link/LandingLink.tsx +++ b/frontend/src/components/landing/link/LandingLink.tsx @@ -1,15 +1,42 @@ import { useModal } from "../../../hooks/common/modal/useModal"; -import { LandingLinkDTO } from "../../../types/DTO/landingDTO"; +import { LandingDTO, LandingLinkDTO } from "../../../types/DTO/landingDTO"; import LandingLinkBlock from "./LandingLinkBlock"; import LandingLinkModal from "./LandingLinkModal"; import LandingTitleUI from "../common/LandingTitleUI"; +import { Socket } from "socket.io-client"; +import { useOutletContext } from "react-router-dom"; +import { useEffect, useState } from "react"; +import { + LandingSocketData, + LandingSocketDomain, +} from "../../../types/common/landing"; + +const LandingLink = () => { + const { socket }: { socket: Socket } = useOutletContext(); + const [link, setLink] = useState([]); + const handleInitEvent = (content: LandingDTO) => { + const { link } = content as LandingDTO; + setLink(link); + }; -const LandingLink = ({ link }: { link: LandingLinkDTO[] }) => { const { open, close } = useModal(true); const handleCreateLinkClick = () => { open(); }; + const handleOnLanding = ({ domain, content }: LandingSocketData) => { + if (domain !== LandingSocketDomain.INIT) return; + handleInitEvent(content); + }; + + useEffect(() => { + socket.on("landing", handleOnLanding); + + return () => { + socket.off("landing"); + }; + }, [socket]); + return (
diff --git a/frontend/src/pages/landing/LandingPage.tsx b/frontend/src/pages/landing/LandingPage.tsx index 45e637a..fe43478 100644 --- a/frontend/src/pages/landing/LandingPage.tsx +++ b/frontend/src/pages/landing/LandingPage.tsx @@ -15,7 +15,7 @@ const LandingPage = () => { } const { socket }: { socket: Socket } = useOutletContext(); - const { project, myInfo, member, link, memoList, inviteLinkIdRef } = + const { project, myInfo, member, memoList, inviteLinkIdRef } = useLandingSocket(socket); const { memoSocketEvent } = useLandingEmitEvent(socket); @@ -31,7 +31,7 @@ const LandingPage = () => { {...{ member, myInfo, inviteLinkIdRef }} projectTitle={project.title} /> - +
); From e6f6377ba3831f86ad67c1a185d6c86b95628ae9 Mon Sep 17 00:00:00 2001 From: "dongind.oct" Date: Thu, 6 Jun 2024 16:11:18 +0900 Subject: [PATCH 05/12] =?UTF-8?q?refactor=20:=20MemoList=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=EC=97=90=20=EC=9B=B9=EC=86=8C=EC=BC=93=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=20=EC=A7=81=EC=A0=91=20=EC=A3=BC=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../landing/memo/LandingMemoList.tsx | 92 ++++++++++++++++--- frontend/src/pages/landing/LandingPage.tsx | 7 +- 2 files changed, 79 insertions(+), 20 deletions(-) diff --git a/frontend/src/components/landing/memo/LandingMemoList.tsx b/frontend/src/components/landing/memo/LandingMemoList.tsx index 718758d..39e285c 100644 --- a/frontend/src/components/landing/memo/LandingMemoList.tsx +++ b/frontend/src/components/landing/memo/LandingMemoList.tsx @@ -1,23 +1,85 @@ -import { LandingMemoDTO } from "../../../types/DTO/landingDTO"; -import { MemoColorType } from "../../../types/common/landing"; +import { Socket } from "socket.io-client"; +import { LandingDTO, LandingMemoDTO } from "../../../types/DTO/landingDTO"; +import { + LandingSocketData, + LandingSocketDomain, + LandingSocketMemoAction, + MemoColorType, +} from "../../../types/common/landing"; import LandingTitleUI from "../common/LandingTitleUI"; import MemoBlock from "./MemoBlock"; +import { useOutletContext } from "react-router-dom"; +import { useEffect, useState } from "react"; -interface LandingMemoListProps { - memoList: LandingMemoDTO[]; - memoSocketEvent: { - emitMemoCreateEvent: () => void; - emitMemoDeleteEvent: (id: number) => void; - emitMemoColorUpdateEvent: (id: number, color: MemoColorType) => void; +const LandingMemoList = () => { + const { socket }: { socket: Socket } = useOutletContext(); + const [memoList, setMemoList] = useState([]); + + const handleInitEvent = (content: LandingDTO) => { + const { memoList } = content as LandingDTO; + setMemoList(memoList); + }; + + const handleMemoEvent = ( + action: LandingSocketMemoAction, + content: LandingMemoDTO + ) => { + switch (action) { + case LandingSocketMemoAction.CREATE: + setMemoList((memoList: LandingMemoDTO[]) => { + return [content, ...memoList]; + }); + break; + case LandingSocketMemoAction.DELETE: + setMemoList((memoList: LandingMemoDTO[]) => { + return memoList.filter( + (memo: LandingMemoDTO) => memo.id !== content.id + ); + }); + break; + case LandingSocketMemoAction.COLOR_UPDATE: + setMemoList((memoList: LandingMemoDTO[]) => { + return memoList.map((memo: LandingMemoDTO) => { + if (memo.id !== content.id) return memo; + return { ...memo, color: content.color }; + }); + }); + } + }; + const handleOnMemoLanding = ({ + domain, + action, + content, + }: LandingSocketData) => { + console.log(domain, action, content); + switch (domain) { + case LandingSocketDomain.INIT: + handleInitEvent(content); + break; + case LandingSocketDomain.MEMO: + console.log("memo editing"); + handleMemoEvent(action, content); + break; + } + }; + const emitMemoCreateEvent = () => { + socket.emit("memo", { action: "create", content: { color: "yellow" } }); }; -} + const emitMemoDeleteEvent = (id: number) => { + socket.emit("memo", { action: "delete", content: { id } }); + }; + const emitMemoColorUpdateEvent = (id: number, color: MemoColorType) => { + socket.emit("memo", { action: "colorUpdate", content: { id, color } }); + }; + + useEffect(() => { + socket.on("landing", handleOnMemoLanding); + + return () => { + socket.off("landing"); + }; + }, [socket]); -const LandingMemoList = ({ - memoList, - memoSocketEvent, -}: LandingMemoListProps) => { - const { emitMemoCreateEvent, emitMemoDeleteEvent, emitMemoColorUpdateEvent } = - memoSocketEvent; return (
diff --git a/frontend/src/pages/landing/LandingPage.tsx b/frontend/src/pages/landing/LandingPage.tsx index fe43478..6679fdc 100644 --- a/frontend/src/pages/landing/LandingPage.tsx +++ b/frontend/src/pages/landing/LandingPage.tsx @@ -6,7 +6,6 @@ import LandingLink from "../../components/landing/link/LandingLink"; import { Socket } from "socket.io-client"; import useLandingSocket from "../../hooks/common/socket/useLandingSocket"; import LandingMemoList from "../../components/landing/memo/LandingMemoList"; -import useLandingEmitEvent from "../../hooks/common/socket/useLandingEmitEvent"; const LandingPage = () => { const { projectId } = useParams(); @@ -15,15 +14,13 @@ const LandingPage = () => { } const { socket }: { socket: Socket } = useOutletContext(); - const { project, myInfo, member, memoList, inviteLinkIdRef } = - useLandingSocket(socket); - const { memoSocketEvent } = useLandingEmitEvent(socket); + const { project, myInfo, member, inviteLinkIdRef } = useLandingSocket(socket); return (
- +
From 6a8e9500fc9697764593ca770cae86997777975d Mon Sep 17 00:00:00 2001 From: "dongind.oct" Date: Thu, 6 Jun 2024 20:02:03 +0900 Subject: [PATCH 06/12] =?UTF-8?q?fix=20:=20websocket=20=EC=9D=B4=EB=B2=A4?= =?UTF-8?q?=ED=8A=B8=20=EB=A6=AC=EC=8A=A4=EB=84=88=EA=B0=80=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=EB=90=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - webSocket 이벤트 리스너를 등록하는 useEffect에 불필요한 dependency array를 전달 - dependancy array에 socket 객체를 넣은 배열을 전달했고, 그로 인해 재렌더링 시 socket이 변화하지 않았기 때문에 이벤트 리스너를 다시 등록하는 콜백함수가 실행되지 않았음 - useEffect 내에 socket 객체를 가지고 있는 dependancy array를 제거 --- frontend/src/components/landing/link/LandingLink.tsx | 2 +- frontend/src/components/landing/memo/LandingMemoList.tsx | 2 +- frontend/src/components/landing/project/LandingProject.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/landing/link/LandingLink.tsx b/frontend/src/components/landing/link/LandingLink.tsx index 9aef1f2..507b97f 100644 --- a/frontend/src/components/landing/link/LandingLink.tsx +++ b/frontend/src/components/landing/link/LandingLink.tsx @@ -35,7 +35,7 @@ const LandingLink = () => { return () => { socket.off("landing"); }; - }, [socket]); + }); return (
diff --git a/frontend/src/components/landing/memo/LandingMemoList.tsx b/frontend/src/components/landing/memo/LandingMemoList.tsx index 39e285c..97f716d 100644 --- a/frontend/src/components/landing/memo/LandingMemoList.tsx +++ b/frontend/src/components/landing/memo/LandingMemoList.tsx @@ -78,7 +78,7 @@ const LandingMemoList = () => { return () => { socket.off("landing"); }; - }, [socket]); + }); return (
diff --git a/frontend/src/components/landing/project/LandingProject.tsx b/frontend/src/components/landing/project/LandingProject.tsx index 3e3a98c..dd59d7e 100644 --- a/frontend/src/components/landing/project/LandingProject.tsx +++ b/frontend/src/components/landing/project/LandingProject.tsx @@ -37,7 +37,7 @@ const LandingProject = ({ projectId }: LandingProjectProps) => { return () => { socket.off("landing"); }; - }, [socket]); + }); return (
From 69926d3d2348d8a830a35467ac7a6252f0bbb028 Mon Sep 17 00:00:00 2001 From: "dongind.oct" Date: Thu, 6 Jun 2024 20:10:09 +0900 Subject: [PATCH 07/12] =?UTF-8?q?refactor=20:=20LandingMemoList=EC=9D=98?= =?UTF-8?q?=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20=EC=83=81=ED=83=9C?= =?UTF-8?q?=EA=B0=92=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기존의 LandingMemoList의 경우, 서버로부터 받아온 Memo 상태값 이외에도 자체적인 title, content, color 상태값을 관리하고 있었다. - 이로인해 불필요하게 상태값 사이의 관계가 복잡해지고 이를 컨트롤, 유지 보수하는데 문제가 많았다. - 이러한 추가적인 상태값을 제거하여 더 관리를 용이하게 만들고자 함 --- .../landing/memo/LandingMemoList.tsx | 2 - .../src/components/landing/memo/MemoBlock.tsx | 34 +++++++---------- .../landing/memo/MemoColorButton.tsx | 5 +-- .../components/landing/memo/MemoEditor.tsx | 6 --- .../hooks/common/landing/useLandingMemo.tsx | 37 +------------------ 5 files changed, 16 insertions(+), 68 deletions(-) diff --git a/frontend/src/components/landing/memo/LandingMemoList.tsx b/frontend/src/components/landing/memo/LandingMemoList.tsx index 97f716d..6102e25 100644 --- a/frontend/src/components/landing/memo/LandingMemoList.tsx +++ b/frontend/src/components/landing/memo/LandingMemoList.tsx @@ -51,13 +51,11 @@ const LandingMemoList = () => { action, content, }: LandingSocketData) => { - console.log(domain, action, content); switch (domain) { case LandingSocketDomain.INIT: handleInitEvent(content); break; case LandingSocketDomain.MEMO: - console.log("memo editing"); handleMemoEvent(action, content); break; } diff --git a/frontend/src/components/landing/memo/MemoBlock.tsx b/frontend/src/components/landing/memo/MemoBlock.tsx index 856ad90..01dea07 100644 --- a/frontend/src/components/landing/memo/MemoBlock.tsx +++ b/frontend/src/components/landing/memo/MemoBlock.tsx @@ -17,18 +17,8 @@ const MemoBlock = ({ emitMemoColorUpdateEvent, emitMemoDeleteEvent, }: MemoBlockProps) => { - const { - editorOpened, - memoTitle, - memoContent, - memoColor, - memoRef, - openEditor, - changeMemoColor, - handleContentChange, - handleTitleChange, - } = useLandingMemo(title, content, color); - const colorStyle = MemoColorStyle[memoColor]; + const { editorOpened, memoRef, openEditor } = useLandingMemo(); + const colorStyle = MemoColorStyle[color]; return (