From 4dcf6980770076f7733d04d4918af256c5bcf95c Mon Sep 17 00:00:00 2001 From: useonglee Date: Mon, 14 Jun 2021 22:26:46 +0900 Subject: [PATCH 1/5] Set #409 changed parameter name from chatBucket to chatData --- src/utils/chatSection.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/chatSection.ts b/src/utils/chatSection.ts index cad97ce..0e3f9b2 100644 --- a/src/utils/chatSection.ts +++ b/src/utils/chatSection.ts @@ -4,10 +4,10 @@ import 'dayjs/locale/ko'; import { ChatDataType, ChatSectionType } from '../types/types'; dayjs.locale('ko'); -export const chatSection = (chatBucket: ChatDataType[]): ChatSectionType => { +export const chatSection = (chatData: ChatDataType[]): ChatSectionType => { const sections: ChatSectionType = {}; - chatBucket.forEach(chat => { + chatData.forEach(chat => { const monthDate = dayjs(chat.createdAt).format('M월 D일 ddd요일'); if (Array.isArray(sections[monthDate])) { From fffea9aea9be097c0a5b6135813b3cfe7e0c4841 Mon Sep 17 00:00:00 2001 From: useonglee Date: Mon, 14 Jun 2021 22:27:17 +0900 Subject: [PATCH 2/5] Add #409 chat slice reducer --- src/reducer/chat.ts | 54 ++++++++++++++++++++++++++++++++++++++++++++ src/reducer/index.ts | 6 +++-- 2 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 src/reducer/chat.ts diff --git a/src/reducer/chat.ts b/src/reducer/chat.ts new file mode 100644 index 0000000..bbfb9ad --- /dev/null +++ b/src/reducer/chat.ts @@ -0,0 +1,54 @@ +import { createSlice, PayloadAction } from '@reduxjs/toolkit'; +import { RootStateOrAny } from 'react-redux'; + +import { ChatDataType } from '../types/types'; + +// TODO: 초기 상태 +const initialState: ChatDataType[] = [ + // { + // id: -1, + // text: '', + // uploadImage: '', + // room: '', + // index: -1, + // writer: { + // id: null, + // name: '', + // email: '', + // mobile: '', + // gitId: '', + // career: { + // office: '', + // job: '', + // period: '', + // }, + // aboutMe: '', + // uploadImage: '', + // profileColor: '', + // createdAt: '', + // updatedAt: '', + // }, + // createdAt: '', + // project: undefined, + // foundChat: undefined, + // chat: undefined, + // }, +]; + +// TODO: slice 실행 +export const chatSlice = createSlice({ + name: 'chat', + initialState, + reducers: { + getAllMessages: (state, { payload }: PayloadAction) => { + return [...payload, ...state]; + }, + sendMessages: (state, { payload }: PayloadAction) => { + return [...state, ...payload]; + }, + }, +}); + +export const { getAllMessages, sendMessages } = chatSlice.actions; + +export const getChatDataSelector = (state: RootStateOrAny): ChatDataType[] => state.chatSlice; diff --git a/src/reducer/index.ts b/src/reducer/index.ts index 3a6fb5b..b147b36 100644 --- a/src/reducer/index.ts +++ b/src/reducer/index.ts @@ -1,6 +1,6 @@ import { profileEditInfoSlice } from './profileEdit'; import { combineReducers, configureStore, getDefaultMiddleware } from '@reduxjs/toolkit'; -// import logger from 'redux-logger'; +import logger from 'redux-logger'; import { profileInfoSlice } from './profile'; import { recruitCreateSlice } from './recruitCreate'; @@ -9,6 +9,7 @@ import { roomsListInfoSlice } from './roomsList'; import { kanbanDataSlice } from './kanban'; import { projectInfoSlice } from './projectInfo'; import { loginSlice } from './login'; +import { chatSlice } from './chat'; const reducer = combineReducers({ profileInfoSlice: profileInfoSlice.reducer, @@ -19,9 +20,10 @@ const reducer = combineReducers({ kanbanDataSlice: kanbanDataSlice.reducer, projectInfoSlice: projectInfoSlice.reducer, loginSlice: loginSlice.reducer, + chatSlice: chatSlice.reducer, }); export default configureStore({ reducer, - middleware: [...getDefaultMiddleware()], + middleware: [...getDefaultMiddleware(), logger], }); From 936b9bdc04ae772631d54bd805cd6626afb884a4 Mon Sep 17 00:00:00 2001 From: useonglee Date: Mon, 14 Jun 2021 22:28:54 +0900 Subject: [PATCH 3/5] Refactor #409 clear useState and refactor with redux --- src/components/Chat/ChatContainer/index.tsx | 42 ++++++----------- src/components/Chat/ChatItem/index.tsx | 21 +++++---- src/components/Chat/ChatZone/index.tsx | 51 +++++++-------------- src/components/Chat/Textarea/index.tsx | 20 +++----- 4 files changed, 48 insertions(+), 86 deletions(-) diff --git a/src/components/Chat/ChatContainer/index.tsx b/src/components/Chat/ChatContainer/index.tsx index dd62217..6a782a1 100644 --- a/src/components/Chat/ChatContainer/index.tsx +++ b/src/components/Chat/ChatContainer/index.tsx @@ -3,19 +3,22 @@ import { getProfileInfoSelector } from '../../../reducer/profile'; import ChatZone from '../ChatZone'; import Textarea from '../Textarea'; import useSocket from '../../../hooks/useSocket'; -import { chatSection } from '../../../utils/chatSection'; import { getChatData, newChatData } from '../../../utils/ChatSocketData'; -import { useSelector } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import { useHistory, useParams } from 'react-router'; import { Scrollbars } from 'react-custom-scrollbars'; import { AllMessagesDataType, ChatDataType, ChatIdType, ChatUpdateDataType } from '../../../types/types'; +import { getAllMessages, getChatDataSelector, sendMessages } from '../../../reducer/chat'; const WorkSpaceChat = (): JSX.Element => { const profileInfo = useSelector(getProfileInfoSelector); + const chatData = useSelector(getChatDataSelector); + const { projectUrl, part: room } = useParams<{ projectUrl: string; part: string }>(); const history = useHistory(); + const dispatch = useDispatch(); const currentAddress = history.location.pathname.split('/')[3]; const [socket, connectionSocket, disconnectSocket] = useSocket(projectUrl, currentAddress); const scrollbarRef = useRef(null); @@ -46,9 +49,9 @@ const WorkSpaceChat = (): JSX.Element => { } setIsEnd(isEnd); - setChatBucket([...chats, ...chatBucket]); + dispatch(getAllMessages(chats)); }); - }, [chatBucket]); + }, [chatData]); useEffect(() => { // TODO: room이 바뀌면 room과 다시 연결한다. @@ -67,7 +70,7 @@ const WorkSpaceChat = (): JSX.Element => { // TODO: 메세지를 받으면 재렌더링 한다. socket?.on('sendMessage', (chat: ChatDataType) => { if (chat) { - setChatBucket([...chatBucket, chat]); + dispatch(sendMessages([chat])); } }); @@ -100,14 +103,14 @@ const WorkSpaceChat = (): JSX.Element => { setChatBucket([...chatBucket, chat]); } }); - }, [chatBucket]); + }, [chatData]); // TODO: 스크롤바는 항상 맨 밑에 위치한다. useEffect(() => { if (chatBucket && order === 0) { scrollbarRef.current?.scrollToBottom(); } - }, [chatBucket]); + }, [chatData]); // TODO: 채팅 입력 const onSubmitForm = useCallback( @@ -117,13 +120,13 @@ const WorkSpaceChat = (): JSX.Element => { return; } - const data: ChatUpdateDataType = getChatData(room, profileInfo, chat, chatBucket.length); + const data: ChatUpdateDataType = getChatData(room, profileInfo, chat, chatData.length); const newChat: ChatDataType = newChatData(-1, chat, '', room, profileInfo); socket?.emit('sendMessage', data); if (chat) { - setChatBucket([...chatBucket, newChat]); + dispatch(sendMessages([newChat])); setChat(''); } @@ -131,38 +134,21 @@ const WorkSpaceChat = (): JSX.Element => { scrollbarRef.current.scrollToBottom(); } }, - [chat, chatBucket], + [chat, chatData], ); const onChangeChatValue: React.ChangeEventHandler = useCallback((e): void => { setChat(e.target.value); }, []); - const chatSections = chatSection(chatBucket ? [...chatBucket] : []); - const isEmpty = chatBucket.length === 0; - const isReachingEnd = isEmpty || (chatBucket && chatBucket.length < 30); - return ( <> - +