devcisive / solumon-frontend

0 stars 3 forks source link

입력한 채팅이 중복 렌더링(?) 되는 문제 #65

Open chaeeunj opened 9 months ago

chaeeunj commented 9 months ago

채팅 코드 전문


import { useState, useEffect, useRef } from 'react';
import * as Stomp from '@stomp/stompjs';
import styled, { ThemeProvider } from 'styled-components';
import theme from '../style/theme';
import PropTypes from 'prop-types';

const Chat = ({ postId }) => { const [message, setMessage] = useState(''); const [messageLists, setMessageLists] = useState([]); const stompClient = useRef(null);

const userInfo = JSON.parse(window.localStorage.getItem('userInfo')); const USER_TOKEN = userInfo.accessToken;

useEffect(() => { const websocket = new WebSocket(ws://13.124.61.246:8080/ws-stomp); stompClient.current = new Stomp.Client({ webSocketFactory: () => websocket, connectHeaders: { 'X-AUTH-TOKEN': USER_TOKEN, }, debug: function (str) { console.log(str); }, });

stompClient.current.onConnect = () => {
  console.log('STOMP 연결 성공');
  stompClient.current.subscribe(`/sub/chat/${postId}`, (message) => {
    const newMessage = JSON.parse(message.body);
    console.log(newMessage);
    displayMessage(newMessage);
    console.log(messageLists);
  });
};

stompClient.current.onStompError = (frame) => {
  console.error('STOMP 연결 에러:', frame);
};

stompClient.current.activate();

return () => {
  stompClient.current.deactivate();
};

}, [postId, USER_TOKEN]);

const handleMessageChange = (e) => { setMessage(e.target.value); };

const sendMessage = () => { if (message.trim() === '') return; if (stompClient.current && stompClient.current.connected) { const newMessage = { contents: message, }; stompClient.current.publish({ destination: /pub/chat/${postId}, body: JSON.stringify(newMessage.contents), });

  setMessage('');
} else {
  console.error('WebSocket 연결이 아직 완료되지 않았습니다.');
}

};

const displayMessage = (message) => { setMessageLists((prevMessageLists) => [...prevMessageLists, message]); };

return (

{messageLists.length > 0 && messageLists.map((message, index) => ( {message.nickname} {message.contents} ))}

); };

Chat.propTypes = { postId: PropTypes.string.isRequired, accessToken: PropTypes.string, };

export default Chat;

const ChatBox = styled.div width: fit-content; padding: 15px; background-color: ${({ theme }) => theme.linen}; margin-bottom: 20px; ;


</br>

웹소켓으로 stomp 연결 후 채팅을 입력하면 잘 전송되는 것을 확인했으나
![image](https://github.com/devcisive/solumon-frontend/assets/72565344/1bc86fea-e7cf-4b02-b2a7-0d63b42f45cf)

위의 사진과 같이 입력한 채팅만 렌더링되지 않고 빈 ChatBox가 한 개 더 렌더링 되는 문제가 있습니다.

</br>

문제의 원인을 찾아보기 위해 채팅방을 구독하는 subscribe 함수에서 받아오는 message 값을 확인하려고 `console.log(newMessage);` 코드를 작성했습니다.
``` javascript
    stompClient.current.onConnect = () => {
      console.log('STOMP 연결 성공');

      stompClient.current.subscribe(`/sub/chat/${postId}`, (message) => {
        const newMessage = JSON.parse(message.body);
        console.log(newMessage);
        displayMessage(newMessage);
        console.log(messageLists);
      });
    };


해당 코드는 Chat 컴포넌트의 31번째 줄에 위치하고 있는데, 콘솔창을 확인해보면 채팅 전송 시 console.log(newMessage); 코드가 2번 실행됐음을 알 수 있습니다. image

사진과 같이 첫 번째에는 입력한 채팅이 콘솔창에 그대로 출력되는데, 두 번째에는 채팅 전달 상태와 관련되어 보이는 코드가 출력되는 것을 확인했습니다.


그리고 누적된 채팅 목록들을 확인하기 위해 console.log(messageLists); 코드를 실행하면 아래와 같은 결과가 출력되는 것을 확인했습니다. image messageLists배열에는 채팅 목록들만 담겨있어야 하는데


image body가 null값이며 상태코드를 나타내는 객체도 함께 담겨있어서 빈 ChatBox가 한 개 더 렌더링되는 문제가 발생한거라고 생각이 됩니다.

chaeeunj commented 9 months ago

해결 시도1

제대로 전송된 채팅들은 contents 값을 가지고 있기 때문에 조건문을 사용해서 contents 값이 있을 때만 ChatBox를 렌더링 하도록 코드를 수정했습니다.

messageLists.map(
              (message) =>
                message.contents && (
                  <ChatBox key={message.contents}>
                    <span>{message.nickname}</span> {message.contents}
                  </ChatBox>
                ),
            )}


결과적으로 이전처럼 빈 ChatBox가 렌더링되는 문제는 발생하지 않지만 올바른 해결 방식이 맞는지 의문이 듭니다. image 조건부 렌더링으로 오류를 해결하는 것이 아니라 처음부터 전송한 채팅만을 messageLists 배열에 저장하는 방법이 무엇인지 고민하고 있습니다. (아래 사진과 같은 코드는 저장되지 않고) image