Множественная отправка сообщений через WebSocket

Пишу онлайн чат на Spring WebSocket и ReactJs.

Проблема в дублировании сообщения при отправке, при чем с каждым новым сообщением дубликатов все больше.

Консоль

Код:

  const Message = () => {
  const dispatch = useDispatch();
  const { message, auth } = useSelector((store) => store);
  const [currentChat, setCurrentChat] = useState();
  const [messages, setMessages] = useState([]);
  const [selectedImage, setSelectedImage] = useState();
  const [isLoading, setIsLoading] = useState(false);
  const chatContainerRef = useRef(null);
  const stompClientRef = useRef(null);

  useEffect(() => {
    dispatch(getAllChats());
  }, [message.message]);

  const handleSelectImage = async (e) => {
    setIsLoading(true);
    console.log("select image");
    const imgUrl = await uploadToCloud(e.target.files[0], "image");
    setSelectedImage(imgUrl);
    setIsLoading(false);
  };

  const handleCreateMessage = (value) => {
    const message = {
      chatId: currentChat?.id,
      content: value,
      image: selectedImage,
    };
    dispatch(createMessage({ message, sendMessageToServer }));
  };

  useEffect(() => {
      dispatch(getMessagesChat(currentChat?.id))
  }, []);

  const [stompClient, setStomClient] = useState();

  useEffect(() => {
    const sock = new SockJS("http://localhost:8080/ws");
    const stomp = Stomp.over(sock);
    setStomClient(stomp);

    stomp.connect({}, onConnect, onErr);
  }, []);

  const onConnect = () => {
    //TODO
    console.log("websocket connected...");
  };

  const onErr = (error) => {
    //TODO
    console.log("errr", error);
  };

  useEffect(() => {
    if (stompClient && auth.user && currentChat) {
      const subscription = stompClient.subscribe(
        `/user/${currentChat.id}/private`,
        onMessageReceive
      );
    }
  });

  const sendMessageToServer = (newMessage) => {
    if (stompClient && newMessage) {
      stompClient.send(
        `/app/chat/${currentChat?.id.toString()}`,
        {},
        JSON.stringify(newMessage)
      );
    }
  };

  const onMessageReceive = (payload) => {
    const recivedMessage = JSON.parse(payload.body);
    console.log("message revice from websocket", recivedMessage);

    setMessages((prevMessages) => [...prevMessages, recivedMessage]);
  };

  useEffect(() => {
    if (chatContainerRef.current) {
      chatContainerRef.current.scrollTop =
        chatContainerRef.current.scrollHeight;
    }
  }, [messages]);

В базе данных все отлично, сохраняется в одном экземпляре, также если обновить страницу то все сообщения отображаются корректно по одному. Надеюсь на Вашу помощь, только начал осваивать Реакт и ВебСокет.


Ответы (1 шт):

Автор решения: Владислав Карпенко

Решение - проверять наличие подписки

const [isSubscribed, setIsSubscribed] = useState(false);

 useEffect(() => {
    if (stompClient && auth.user && currentChat && !isSubscribed) {
      const subscription = stompClient.subscribe(
        `/user/${currentChat.id}/private`,
        onMessageReceive
      );
      setIsSubscribed(true);
    }
  });
→ Ссылка