[React] 채팅방 메시지 트러블슈팅 (onKeyPress 선언, 키값 중복)

planted-ji·2023년 6월 20일
0
post-thumbnail

Error (1). 선언이 여기에 사용되지 않음으로 표시되었습니다

메시지를 입력한 TextInput에서 Enter 키를 눌렀을 때, onKeyPress를 통해 메시지가 전송되는 코드를 작성했다. 코드에는 문제가 없는데 이상하게 onKeyPress 위에 밑줄이 그어져서 확인했더니 이런 메시지 창이 떴다.

원인

"선언이 여기에 사용되지 않음으로 표시" 라는 내용이 무슨 뜻인지 찾아보니, 곧 사용이 중지되는 속성이므로 사용을 지양해달라는 경고라고 한다.

해결

그래서 아래처럼 onKeyPress를 onKeyDown으로 수정했다.

<TextInput
  type="text"
  value={content}
  placeholder="메시지 입력하기…"
  onChange={handleMessageInput}
  onKeyDown={e => {
    if (e.key === "Enter" && !e.shiftKey) {
      e.preventDefault();
      handlePostMessage(e);
    }
  }}
/>

Error (2). Encountered two children with the same key

메시지를 전송할 때, 하나의 메시지마다 key를 부여해야 하기 때문에 아래 코드처럼 메시지를 구성하는 요소 중에서 시간을 key로 넣어주었다. 그 탓(덕분에?)에 다시 한 번 오류를 마주하게 된다.

{messages.map(message => (
            <ChatBubble
              key={message.time}
              isReceived={false}
              sentMessage={message.content}
              uploadedImage={message.uploadedImage}
              currentTime={message.time}
            />
          ))}

원인

key는 고유의 값을 가져야 하는데, 같은 시:분에 메시지를 보내면 해당 메시지들은 동일한 key를 가지기 때문에 발생하는 오류였다.

해결

key 뒤에 index를 추가하기

시간:분이 동일해도 따라오는 index 값이 다르면 고유한 key가 될 수 있겠다는 생각이 들어 아래와 같이 코드를 수정했다.

{messages.map((message, index) => (
  <ChatBubble
    key={`${message.time}-${index}`}
    isReceived={false}
    sentMessage={message.content}
    uploadedImage={message.uploadedImage}
    currentTime={message.time}
  />
))}

Do not use Array index in keys

그러나, 예상을 깨고 또 한 번 오류가 발생하는데 이는 배열 인덱스를 key로 사용하지 않도록 권장하는 React의 규칙 때문이었다. (배열 인덱스를 key로 사용하면 항목 순서가 변경되거나 목록에서 항목이 추가 또는 제거될 때 문제가 발생할 수 있다는 이유)

오류를 해결하기 위해 index를 사용하는 대신 각 메시지에 고유 식별자를 제공하도록 코드를 수정해야만 했다. uuid 라이브러리를 사용할 수도 있지만, 외부 라이브러리를 사용하면 그만큼 무거워질 수 있기에 다른 방식을 생각해봤다.

// * 시간과 함께 메시지 생성
    const currentTime = getCurrentTime();
    const newMessage = {
      key: messageCounter, 
      content,
      uploadedImage,
      time: currentTime
    };
    setMessages(prevMessages => [...prevMessages, newMessage]);
    setMessageCounter(prevCounter => prevCounter + 1);
    setContent("");
    setUploadedImage(null);
    console.log("메시지가 전송되었습니다.", content);

먼저, 고유 키 할당을 위해 증분 카운터 역할을 하는 messageCounter라는 상태 변수를 추가했다. 새 메시지가 게시될 때마다 카운터 값이 메시지의 키로 할당된 다음, 카운터가 1씩 증가하게 만들어 주었다.

이 방법을 통해 외부 라이브러리에 의존하지 않고 메시지 고유 키 생성에 성공했다!

uuid 라이브러리 사용하기

그러나, 프로젝트를 진행하면서 다른 컴포넌트에서도 키값 중복 문제가 여럿 발생하기 시작했고 이를 해결하기 위해 결국 uuid 라이브러리를 도입하기로 했다. uuid를 적용한 코드는 아래와 같다.

import { v4 as uuidv4 } from "uuid";

 // * 시간과 함께 메시지 생성
    const currentTime = getCurrentTime();
    const newMessage = {
      key: uuidv4(),
      content,
      uploadedImage,
      time: currentTime,
    };
    setMessages(prevMessages => [...prevMessages, newMessage]);
    setContent("");
    setUploadedImage(null);
    console.log("메시지가 전송되었습니다.", content);
  };

결과

uuid를 사용해 랜덤한 난수를 key 값으로 주니 더 이상 오류가 발생하지 않는다! 😊 오류 해결!

0개의 댓글