컴포넌트 분리 작업 중
2024. 1. 30. 15:45ㆍ개발
기존에 한 useEffect에 몰아 넣었던 기능들을
하나의 기능마다 분리해서 리팩토링 진행.
위에서부터 각
채팅방 리스트/채팅방메시지/채팅방 메시지 카운트
디펜더시도 다시 만들어 넣어줬더니 굴러는 가는데
아직 가야할 길이 멀다
APP에 몰아 넣은 기능들 코드를 더 줄 일 수 있으면 줄이고,
컴포넌트 따로 빼서 export 할 수 있으면 그렇게 리팩토링 진행할 계획이다
import { useEffect, useState } from 'react';
import { QueryClient, QueryClientProvider } from 'react-query';
import { useRecoilState } from 'recoil';
import { ThemeProvider } from 'styled-components';
import { supabase } from './api/supabase.api';
import {
ChatId,
ChatRoom,
UnreadCounts,
chatRoomsState,
isChatModalOpenState,
newMessagesCountState,
person,
sendMessages,
} from './atom/product.atom';
import { AuthContextProvider } from './contexts/auth.context';
import Router from './shared/Router';
import GlobalStyle from './styles/globalStyle';
import theme from './styles/theme';
type Message = {
author_id: string;
chat_id: string;
content: string;
created_at: string;
id: number;
item_id: number;
others_id: string | null;
};
// Define a type for the payload
type MessagePayload = {
commit_timestamp: string;
errors: null | any; // Replace 'any' with a more specific type if possible
eventType: string;
new: Message;
old?: any; // Replace 'any' with a more specific type if possible
schema: string;
table: string;
};
export type UnreadCount = {
chat_id: string;
unread_count: number;
};
const queryClient = new QueryClient();
const App = () => {
const [chatId, setChatId] = useRecoilState(ChatId);
const [messages, setMessages] = useRecoilState(sendMessages);
const [newMessagesCount, setNewMessagesCount] = useRecoilState(newMessagesCountState);
const [chatRooms, setChatRooms] = useRecoilState(chatRoomsState);
const [ChatBtnOpen, setChatBtnOpen] = useRecoilState(isChatModalOpenState);
const [LoginPersonal, setLoginPersonal] = useRecoilState(person);
const [unreadCounts, setUnreadCounts] = useRecoilState(UnreadCounts);
const [updateMesaage, setUpdateMesaage] = useState<MessagePayload>();
//챗룸 리스트
useEffect(() => {
const fetchChatRooms = async () => {
try {
// 채팅방 ID 가져오기
const { data: chatRoomsData, error: chatRoomsError } = await supabase.from('chats').select('*');
if (chatRoomsError) throw chatRoomsError;
// 각 채팅방에 대해 사용자의 닉네임과 마지막 메시지를 가져오기
const updatedChatRooms = await Promise.all(
chatRoomsData.map(async (chatRoom) => {
const { data: chatUser, error: chatUserError } = await supabase
.from('chats_users')
.select('*')
.eq('chat_id', chatRoom.id);
if (chatUserError) throw chatUserError;
//챗방 마지막 메시지
const { data: lastMessageData, error: lastMessageError } = await supabase
.from('messages')
.select(`content, users(nickname), author_id,item_id,created_at`)
.eq('chat_id', chatRoom.id)
.order('created_at', { ascending: false })
.limit(1)
.maybeSingle();
let sendNickname = '알 수 없음';
let user_img = '알 수 없음';
let product_img = '알 수 없음';
// let unread_count = 0;
const author_id = lastMessageData ? lastMessageData.author_id : '알 수 없음';
if (lastMessageData) {
// lastMessageData가 있는 경우에만 sendNickname과 user_img 설정
if (lastMessageData.author_id) {
const { data: userData, error: userError } = await supabase
.from('users')
.select('*')
.eq('id', lastMessageData.author_id)
.single();
if (userError) throw userError;
if (userData) {
sendNickname = userData.nickname;
user_img = userData.user_img;
}
}
// lastMessageData가 있는 경우에만 product_img 설정
if (lastMessageData.item_id) {
const { data: productData, error: productError } = await supabase
.from('products')
.select('product_img')
.eq('id', lastMessageData.item_id)
.maybeSingle();
if (productError) throw productError;
if (productData) {
product_img = productData.product_img;
}
}
}
return chatUser.map((chatUser) => ({
author_id: author_id,
chat_id: chatRoom.id,
user_id: chatUser.user_id || '알 수 없음',
item_id: chatUser.item_id || '알 수 없음',
lastMessage: lastMessageData ? lastMessageData.content : '메시지가 없습니다.',
sendNickname: sendNickname,
user_img: user_img,
created_at: lastMessageData ? lastMessageData.created_at : '메시지가 없습니다.',
product_img: product_img,
}));
}),
);
// Flatten the array of arrays
const flatChatRooms = updatedChatRooms.flat();
setChatRooms(flatChatRooms as ChatRoom[]);
} catch (error) {
console.error('채팅방 가져오기 오류:', error);
}
};
fetchChatRooms();
//새 메시지 생성시 감지할 채널 구독
const changes = supabase
.channel('schema-db-changes')
.on(
'postgres_changes',
{
event: 'INSERT',
schema: 'public',
table: 'messages',
},
async (payload) => {
console.log('payload', payload);
setUpdateMesaage(payload as MessagePayload);
fetchChatRooms();
},
)
.subscribe();
// 채팅방 변경사항을 감지할 채널 구독
const chatChannel = supabase
.channel('chat-channel')
.on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'chats' }, (payload) => {
fetchChatRooms();
})
.subscribe();
return () => {
changes.unsubscribe();
chatChannel?.unsubscribe();
};
}, [chatId]);
//챗메시지 가져오기
useEffect(() => {
//챗방 메시지 가져오기
const fetchMessages = async () => {
if (chatId) {
// Fetch all messages for the chatId
let { data: messagesData, error: messagesError } = await supabase
.from('messages')
.select('*,users(*)')
.eq('chat_id', chatId);
if (messagesError) {
console.error('메시지를 가져오는 중 오류가 발생했습니다:', messagesError);
return;
}
if (!messagesData) {
setMessages([]);
return;
}
setMessages(messagesData);
}
};
fetchMessages();
//새 메시지 생성시 감지할 채널 구독
const changes = supabase
.channel('schema-db-changes')
.on(
'postgres_changes',
{
event: 'INSERT',
schema: 'public',
table: 'messages',
},
async (payload) => {
console.log('payload', payload);
fetchMessages();
setUpdateMesaage(payload as MessagePayload);
},
)
.subscribe();
return () => {
changes.unsubscribe();
};
}, [chatId, updateMesaage]);
//메시지 카운팅
useEffect(() => {
//메시지 생길때마다, 덧씌워주기
const handleNewMessage = (payload: MessagePayload) => {
setChatRooms((prevChatRooms) =>
prevChatRooms.map((chatRoom) => {
if (chatRoom.chat_id === payload.new.chat_id) {
// 예시: unread_count 업데이트
return {
...chatRoom,
lastMessage: payload.new.content,
created_at: payload.new.created_at,
};
} else {
return chatRoom;
}
}),
);
};
const handleNewMessageCount = (payload: MessagePayload) => {
// 채팅 모달이 열려 있지 않을 때만 새 메시지 수를 증가
if (!ChatBtnOpen) {
setNewMessagesCount((prevCount) => prevCount + 1);
}
};
//읽지않음 카운팅
async function updateUnreadCount() {
const {
data: { user },
} = await supabase.auth.getUser();
if (!user?.id) {
console.log('user not found');
}
const user_id = user?.id;
const { data, error } = await supabase.rpc('count_unread_messages', { user_id });
if (error) {
console.log('읽지 않은 수 업데이트 오류:', error);
} else {
setUnreadCounts(data);
}
}
updateUnreadCount();
//새 메시지 생성시 감지할 채널 구독
const changes = supabase
.channel('schema-db-changes')
.on(
'postgres_changes',
{
event: 'INSERT',
schema: 'public',
table: 'messages',
},
async (payload) => {
console.log('payload', payload);
handleNewMessageCount(payload as MessagePayload);
// 새 메시지 카운트를 증가시킬지 결정하는 함수 호출
handleNewMessage(payload as MessagePayload);
setUpdateMesaage(payload as MessagePayload);
},
)
.subscribe();
// 채팅방 변경사항을 감지할 채널 구독
const chatChannel = supabase
.channel('chat-channel')
.on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'chats' }, (payload) => {
// fetchChatRooms();
})
.subscribe();
return () => {
changes.unsubscribe();
chatChannel?.unsubscribe();
};
}, [chatId, updateMesaage]);
return (
<QueryClientProvider client={queryClient}>
<AuthContextProvider>
<ThemeProvider theme={theme}>
<GlobalStyle />
<Router />
</ThemeProvider>
</AuthContextProvider>
</QueryClientProvider>
);
};
export default App;
'개발' 카테고리의 다른 글
리마인드가 필요하다. (1) | 2024.02.01 |
---|---|
채팅 입력시 끝 단어 2번 입력되는 현상을 발견. (0) | 2024.01.31 |
스파게티 코드 파티~ (4) | 2024.01.29 |
아 중요한 걸 빼먹었네. (2) | 2024.01.26 |
챗 추가 기능 수정 중 (0) | 2024.01.25 |