[chat] 채팅 입/퇴장 문구

miin·2022년 6월 4일
0

Skill Collection [Function]

목록 보기
32/44

결과

full code

https://github.com/suminllll/chatting-sample

내용

  • 채팅방에 유저가 들어오면 ㅇㅇ님이 들어오셨습니다. & 나갔습니다. 표시
  • 본인이 들어오고 나갈때는 본인에게 표시되지 않음

코드

client

import { io } from "socket.io-client";

export default function chatRoom(props) {
const [messages, setMessages] = useState([]); //처음 렌더링시 이전 메세지들을 모두 담음
const { user } = useGuard(); //현재 유저, 사용자 토큰이 있는지 확인후 user 정보를 보내줌

  useEffect(() => {
    socket = io("http://localhost:8000", {
      transports: ["websocket"],
    });
    
    socket.emit("/rooms/join", {
        roomNo: props.roomNo,
        memberNo: user?.member_no,
        nick: user?.nick,
        type: "SYSTEM_USER_IN",
      });

      //채팅방 유저리스트를 서버에서 받아옴
      socket.on("/rooms/join", (data) => {
        console.log("joinuser", data);
      });

      //인삿말
      socket.on("in user notice", (data) => {
        console.log("입장 인삿말", data);

        const notice = {
          type: data.type,
          content: `${data?.nick}님이 들어오셨습니다.`,
        };

        setMessages((message) => [...message, notice]);
      });

	 //채팅방 나가기
      socket.on("/rooms/out", async (data) => {
        console.log("outUser", data);
      });

	//퇴장 인삿말
      socket.on("out user notice", (data) => {
        console.log("퇴장 인삿말", data);

        const notice = {
          type: data.type,
          content: `${data?.nick}님이 나가셨습니다.`,
        };

        //인삿말 반영
        setMessages((messages) => [...messages, notice]);
      });
 	 }, []);

  return (
	<>
	{messages &&
        messages.map((message, index) =>
          message.type === "SYSTEM_USER_IN" ||
          message.type === "SYSTEM_USER_OUT" ? (
        	<div key={key}>
        		<div className="notice">{contents}</div>
     		</div>
			) : null
	}
	</>
	);
}

//getServerSideProps로 미리 roomNo를 받아옴
export const getServerSideProps = async (ctx) => {
  const id = ctx.query.id;

  return {
    props: {
      roomNo: id,
    },
  };
};

server

io.on("connection", (socket) => {
  
  //채팅방 입장시 실행되는 이벤트
  socket.on("/rooms/join", async (data) => {
    console.log("채팅방 입장", data);
    
    // broadcast: 접속한 클라이언트가 들어가있는 방에 있는 사람에게만 데이터를 보내준다
    socket.broadcast.in(roomNo).emit("in user notice", data)
  })
  
  //채팅방 나가기
  socket.on("/rooms/out", (data) => {
    console.log("채팅방 나감", data);
    
    socket.broadcast.in(roomNo).emit("out user notice", data);
  })
});

bug

  • user.nick이 제대로 표시되다가도 나갔다 들어오면 undefinde가 표시됨
  • 위의 내용 + 한 유저에서 두번씩 표시됨
    -> render가 두번씩 발생한다고 생각했다
  • 해결
    • react 문제인줄 알아서 reactStricMode: false를 했는데도 여전히 같은문제,
    • 클라에서 socket 퇴장 인삿말 하는 부분은 userList와 함께 처리하고 있었는데 입장처럼 따로 분리하니 한번만 표시됨
    • messages를 map 돌리는 과정에서 messages && 이면 map돌림

0개의 댓글