PJH's live chat - Chat Box

박정호·2023년 2월 5일
0

Live Chat Project

목록 보기
6/7
post-thumbnail

🚀 Start

socket.io에 대한 설정도 마쳤으니, 이제 실제로 화면에 메시지를 입력하는 기능들을 만들어보자.

👍 사용되는 기능들

  • chatbox : 텍스트를 입력할 입력상자
  • auto - size : 입력 텍스트 양에 따라 chatBox 자동 사이즈 조절
  • enter submit : 키보드의 enter 입력에 따른 메시지 제출
  • react-mention : 해당 채팅방에 존재하는 유저 언급 기능 (@ 사용)
⭐️ client
|
└── 🗂 pages
|	  ├── 🗂 Channel
|     └── 🗂 DirectMessage
|
└── 🗂 components
     └── 🗂 ChatBox


🔤 ChatBox

우선, 메시지를 입력하기 위한 텍스트박스 컴포넌트를 생성하자.


Channel / Direct Message 컴포넌트


 <ChatBox
        onSubmitForm={onSubmitForm} // 제출 
        chat={chat} // 데이터 
        onChangeChat={onChangeChat} // 입력변환 
        placeholder={`Message #${channel}`} // 기본입력값
      	...
      />

ChatBox 컴포넌트

const ChatBox: FC<Props> = ({onSubmitForm,chat,onChangeChat,placeholder}) => {
  
  const textareaRef = useRef<HTMLTextAreaElement>(null);
  	...
  return (
    <ChatArea>
      <Form onSubmit={onSubmitForm}>
        <MentionsTextarea
          id="editor-chat"
          value={chat} // 데이터 
          onChange={onChangeChat} // 입력변환 
          placeholder={placeholder} // 기본입력값
          inputRef={textareaRef} // 입력 텍스트 감지
          allowSuggestionsAboveCursor // 커서 위의 제안 허용
        />
        ...
        <SendButton>제출</SendButton>
      </Form>
    </ChatArea>
  );
};


⌨️ key board

제출 버튼을 클릭할 수도 있지만, 간편하게 키보드의 Enter를 눌러 제출이 가능하게 설정하자.

const onKeydownChat = useCallback(
   (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
     if (e.key === 'Enter') { // enter키 클릭시
       if (!e.shiftKey) { // shiftkey 클릭이 아니라면...
         e.preventDefault();
         onSubmitForm(e); // 제출
       }
     }
   },
   [onSubmitForm]
 );
 
return <MentionsTextarea onKeyPress={onKeydownChat} />


📦 auto size

텍스트에 따른 chatBox 자동 사이즈 조절을 설정하자.

useEffect(() => {
    if (textareaRef.current) {
      autosize(textareaRef.current);
    }
  }, []);


@ react - mention

DM, Channel 컴포넌트에서 해당 채팅방에 속한 사용자 데이터를 받아와 mention 기능에 추가해주자. 그러면 @입력시 언급 가능한 사용자 목록이 출력된다.

Channel / Direct Message 컴포넌트

// Channel
const { data: channelMembersData } = useSWR<IUser[]>(
    userData ? `/api/workspaces/${workspace}/channels/${channel}/members` : null,
    fetcher
  );
return  <ChatBox data={memberData}/>

// Direct Message.
 const { data: memberData } = useSWR<IUserWithOnline[]>(
    userData ? `/api/workspaces/${workspace}/members` : null,
    fetcher
  );
return  <ChatBox data={memberData}/>

ChatBox 컴포넌트

const ChatBox: FC<Props> = ({data}) => {
  	...
   const renderUserSuggestion: (suggestion,search,highlightedDisplay,index,focused) 
     => React.ReactNode = useCallback( (member, search, highlightedDisplay, index, focus) 
     => {
         if (!data) return null;
         return (
            <EachMention focus={focus}>
              <img src={gravatar.url(data[index].email, { s: '20px', d: 'retro' })} alt={data[index].nickname} />
              <span>{highlightedDisplay}</span>
            </EachMention>
      );
    },
    [data]
  );
  	...
  return (
  		 <Mention
            appendSpaceOnAdd
            trigger="@"
            data={data?.map(v => ({ id: v.id, display: v.nickname })) || []}
            renderSuggestion={renderUserSuggestion}
          />
  );
};

💡 설정에 대한 자세한 내용 : React-mentions 공식문서

profile
기록하여 기억하고, 계획하여 실천하자. will be a FE developer (HOME버튼을 클릭하여 Notion으로 놀러오세요!)

0개의 댓글