스파르타코딩클럽/내일배움캠프

postgres_changes로 전달된 데이터 타입

myinfo7091 2024. 12. 27. 12:47

'(prev: { chatroom_id: string; content: string; created_at: string; id: string; sender_id: string; }[]) => ({ chatroom_id: string; content: string; created_at: string; id: string; sender_id: string; } | { ...; })[]' 형식의 인수는 'SetStateAction<{ chatroom_id: string; content: string; created_at: string; id: string; sender_id: string; }[]>' 형식의 매개 변수에 할당될 수 없습니다.

 

payload.new의 타입이 정확히 지정되지 않았기 때문에 에러가 발생한다. payload.new가 Supabase의 postgres_changes 이벤트로 전달된 데이터인데, 타입 추론이 제대로 이루어지지 않았다.

 

payload.new에 타입 지정하기 payload.new는 Message 타입으로 지정해줄 것이다. as Message를 사용하여 명시적으로 타입을 단언해줄 수 있다.

 

 // Supabase Realtime 구독 설정
    const channel = supabase
      .channel(`messages:chatroom_id=eq.${chatroomId}`)
      .on(
        'postgres_changes',
        { event: 'INSERT', schema: 'public', table: 'messages', filter: `chatroom_id=eq.${chatroomId}` },
        (payload) => {
          const newMessage = payload.new as Message;
          setMessages((prev) => [...prev, newMessage]); // 새 메시지 추가
        }
      )
      .subscribe();

    return () => {
      supabase.removeChannel(channel);
    };
  }, [chatroomId]);

 

 

수정한 전체 코드

'use client';

import { Database } from '@/types/supabase';
import { createClient } from '@/utils/supabase/client';
import { useEffect, useState } from 'react';

type Message = Database['public']['Tables']['messages']['Row'];

const ChatRoom = ({ chatroomId }: { chatroomId: string | null }) => {
  const supabase = createClient();

  const [messages, setMessages] = useState<Message[]>([]);
  const [message, setMessage] = useState<string>('');

  useEffect(() => {
    // 채팅방의 메시지 조회
    const fetchMessages = async () => {
      const { data, error } = await supabase.from('messages').select('*, users(*)').eq('chatroom_id', chatroomId);
      console.log(data);
      if (error) {
        console.error('메시지 불러오기 실패:', error);
      } else {
        setMessages(data);
      }
    };
    fetchMessages();

    // Supabase Realtime 구독 설정
    const channel = supabase
      .channel(`messages:chatroom_id=eq.${chatroomId}`)
      .on(
        'postgres_changes',
        { event: 'INSERT', schema: 'public', table: 'messages', filter: `chatroom_id=eq.${chatroomId}` },
        (payload) => {
          const newMessage = payload.new as Message;
          setMessages((prev) => [...prev, newMessage]); // 새 메시지 추가
        }
      )
      .subscribe();

    return () => {
      supabase.removeChannel(channel);
    };
  }, [chatroomId]);

  // 메시지 전송
  const handleSendMessage = async () => {
    if (!message.trim()) return;

    const { error } = await supabase.from('messages').insert({
      chatroom_id: chatroomId,
      sender_id: '5fdcaeb3-b543-442f-9dfd-fafbb1c1b2bc', // 현재 로그인된 사용자 ID 필요
      content: message
    });

    if (error) {
      console.error('메시지 전송 실패:', error);
    } else {
      setMessage('');
    }
  };

  return (
    <div className="p-4 flex flex-col h-full">
      <h3 className="text-lg font-semibold mb-4">채팅방</h3>
      <div className="flex-1 overflow-y-auto">
        {messages.map((message) => (
          <div key={message.id}>
            {message.id}: {message.content}
          </div>
        ))}
      </div>
      <div className="flex items-center p-2 border-t">
        <input
          type="text"
          value={message}
          onChange={(e) => setMessage(e.target.value)}
          placeholder="메시지를 입력하세요..."
          className="flex-1 px-4 py-2 border rounded-lg focus:outline-none"
        />
        <button
          onClick={handleSendMessage}
          className="ml-2 px-4 py-2 bg-blue-500 text-white rounded-lg focus:outline-none"
        >
          전송
        </button>
      </div>
    </div>
  );
};

export default ChatRoom;

'스파르타코딩클럽 > 내일배움캠프' 카테고리의 다른 글

채팅방-갤러리 탭 분리하기  (0) 2025.01.14
Zustand 모달 open/close  (0) 2024.12.27
렌더링 패턴  (0) 2024.12.17
[Typescript]  (1) 2024.12.12
[Next.js] 주요 렌더링 패턴  (1) 2024.12.10