2024.04.18 TIL - 최종프로젝트 24일차 (채팅방 목록 불러오기....)

Innes·2024년 4월 18일
1

TIL(Today I Learned)

목록 보기
119/147

채팅방 목록 불러오기

전체적인 flow

채팅방 불러오기 로직

  • useQuery - action_id에 해당하는 room id들 전부 가져와서 배열에 넣기(useState)

  • useEffect 안에서 map으로 room id들 map해서 전부 다 구독하기 + 채팅방 rooms_info 테이블도 같이 구독하기(새로운 채팅방 추가될때 바로 업데이트 되도록)
    -> 구독할때 room id 가져오는 쿼리키 무효화, 채팅방 내용 가져오는 쿼리키 무효화

  • useQuery로 room id에 해당하는 닉네임, 아바타, 마지막 메시지, 마지막 메시지 시간 가져오기
    -> 구독하고 insert했을때 실행되는 함수 부분에 '가져온 정보 무효화'하는 로직 넣어주기

  • 가져온 정보들은 채팅방 jsx map으로 뿌려주기


1:1 채팅목록 불러오기 코드

// PrivateChatsList.tsx

  const queryClient = useQueryClient();

  // 채팅방 room_id 배열 가져오기
  const { data: roomIds, error } = useQuery({
    queryKey: [QUERY_KEY_PRIVATE_ROOM_IDS],
    queryFn: async () => {
      const response = await getPrivateRoomIds(action_id);
      return response;
    },
  });

  useEffect(() => {
    // 채팅방 테이블 변경사항 구독 - 새 채팅방 insert될때 채팅방 리스트 실시간 업데이트
    const chatRoomsSubscription = supabase.channel(`{${action_id}}`).on(
      "postgres_changes",
      { event: "INSERT", schema: "public", table: "chat_rooms_info" },

      (payload) => {
        queryClient.invalidateQueries({
          queryKey: [QUERY_KEY_PRIVATE_ROOM_IDS],
        });
      },
    );

    return () => {
      chatRoomsSubscription.unsubscribe();
    };
  }, [action_id]);

  useEffect(() => {
    // 채팅내용 구독 - room_id 별로 채팅내용 변경사항 구독
    const subscriptions = roomIds?.map((roomId) => {
      const subscription = supabase
        .channel(`${roomId}`)
        .on(
          "postgres_changes",
          { event: "INSERT", schema: "public", table: "chat_messages" },

          (payload) => {
            queryClient.invalidateQueries({
              queryKey: [QUERY_KEY_PRIVATE_CHATS_LIST],
            }),
              // 채팅방 개설은 되어있지만, 메시지가 하나도 없었던 경우 대비
              queryClient.invalidateQueries({
                queryKey: [QUERY_KEY_PRIVATE_ROOM_IDS],
              });
          },
        )
        .subscribe();

      return subscription;
    });

    return () => {
      subscriptions?.map((subscription) => {
        return subscription.unsubscribe();
      });
    };
  }, [roomIds]);

  // 채팅방 리스트 가져오기
  const { data: privateChatsList, error: privateChatListError } = useQuery({
    queryKey: [QUERY_KEY_PRIVATE_CHATS_LIST],
    queryFn: async () => {
      if (roomIds) {
        return await getPrivateChatsList(roomIds);
      }
      return [];
    },
    enabled: !!roomIds,
  });

  if (error || privateChatListError) {
    return <div>Error</div>;
  }
// privateChat-api.ts

// 액션별 1:1 채팅방 room_id들 배열로 가져오기
export const getPrivateRoomIds = async (action_id: string) => {
  const { data, error } = await supabase
    .from("chat_rooms_info")
    .select("id")
    .eq("action_id", action_id)
    .eq("room_type", "개인");

  if (error) {
    console.log("error", error.message);
    throw error;
  }
  const roomIds = data.map((item) => {
    return item.id;
  });
  return roomIds;
};

// 1:1 채팅방 리스트 가져오기 - 📝 수정 예정(채팅 참가자의 정보를 가져와야함)
export const getPrivateChatsList = async (roomIds: string[]) => {
  const chatPromises = roomIds.map(async (roomId) => {
    const { data, error } = await supabase
      .from("chat_messages")
      .select("created_at, content, room_id, users(display_name, profile_img)")
      .eq("room_id", roomId)
      .order("created_at", { ascending: false })
      .limit(1);

    if (error) {
      console.log(
        `Error fetching chat messages for room ${roomId}: ${error.message}`,
      );
      throw error;
    }

    if (data && data.length > 0) {
      return data[0]; // 가장 최신 메시지 반환
    } else {
      // 메시지 없이 빈 채팅방인 경우
      return;
    }
  });

  const chatList = await Promise.all(chatPromises);
  return chatList;
};

일...일단 성공...! (?) 왜 되지...? 다른건 왜 안됐지..? 😂


로직 복잡... 심지어 useQuery를 useEffect 위에서 썼는데 되고, 두번째 useQuery도 같이 useEffect위로 올리니까 에러가 났다.
roomIds를 가져오는 로직에서 몇시간을 애를 먹었다. 결국 되긴 됐는데... 아직 찜찜한 상황인 것 같다. 뭐 하나 잘못 건드리면 와르르 되는 상태랄까...흑
예를 들면, useQuery로 가져온 roomIds가 undefined일 수 있으니까 처리하려고 아래에 if문 넣었더니 바로 에러가 난다.
그래서 그냥 가만히 둬야함....(?)

🤯 다양하게 해봤던 시도들

  • 처음엔 roomIds를 useState로 정해놓고, room_id들 배열 가져와서 set해주는 fetchData 비동기 함수를 useEffect 안에서 실행했다가, 무한대로 계속 roomIds를 업데이트해서 실패
  • fetchData를 useEffect 밖에다 두고 useEffect에서는 실행만 해보기
  • room_id들 가져와서 set하는 로직만 따로 useEffect 분리해보기
    (근데 이렇게 하면 새로운 채팅방이 insert됐을때 roomIds state가 저절로 업데이트되지 않기 때문에 옳은 방법이 아니었음)
  • useQuery로 room_id들 가져와보기
    (이후로 이리저리 useQuery를 이리저리 위치도 이동해보고, 별의 별 짓을 다했다.)
profile
무서운 속도로 흡수하는 스폰지 개발자 🧽

0개의 댓글