결과
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();
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
}
</>
);
}
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);
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돌림