본문 바로가기
개발/React

리액트 - chat-ui-kit-react로 채팅창 UI 만들기 (React Chat UI)

by 피로물든딸기 2024. 3. 24.
반응형

리액트 전체 링크

 

참고

- https://www.npmjs.com/package/@chatscope/chat-ui-kit-react

 

chat-ui-kit-react로 채팅창 UI 만들기
로그인 + 채팅방 UI 만들기
채팅방 변경하기
채팅방 들어오고 나갈 때 표시하기
Socket.IO로 채팅하기
Socket.IO Room으로 채팅방 관리하기
Socket.IO namespace로 채팅방 관리하기
Socket.IO로 중복 로그인 제한하기

- Socket.IO Middleware로 중복 로그인 방지하기

 

chat-ui-kit-react를 이용해서 채팅 UI를 만들어보자.

 

먼저 라이브러리를 설치한다.

npm install @chatscope/chat-ui-kit-react

 

예시 코드는 다음과 같다.

import React from "react";

import styles from "@chatscope/chat-ui-kit-styles/dist/default/styles.min.css";

import {
  MainContainer,
  ChatContainer,
  MessageList,
  Message,
  MessageInput,
  Avatar,
} from "@chatscope/chat-ui-kit-react";

const AVATAR_IMAGE = "https://img1.daumcdn.net/thumb/C428x428/?scode=mtistory2&fname=https%3A%2F%2Ftistory3.daumcdn.net%2Ftistory%2F4431109%2Fattach%2F3af65be1d8b64ece859b8f6d07fafadc";
                  
const ChatUI = () => {
  return (
    <div>
      <div style={{ position: "relative", height: "500px" }}>
        <MainContainer>
          <ChatContainer>
            <MessageList>
              <Message
                model={{
                  direction: "incoming",
                  type: "custom",
                }}
              >
                <Avatar
                  src={AVATAR_IMAGE}
                  name="Akane"
                />
                <Message.CustomContent>
                  <strong>This is strong text</strong>
                  <br />
                  Message content is provided as{" "}
                  <span
                    style={{
                      color: "red",
                    }}
                  >
                    {" "}
                    custom elements
                  </span>{" "}
                  from child <strong>Message.CustomContent</strong> element
                </Message.CustomContent>
              </Message>
              <Message
                model={{
                  message: "Hello my friend",
                  sentTime: "15 mins ago",
                  direction: "outgoing",
                  position: "first",
                }}
              />
              <Message
                model={{
                  direction: "incoming",
                  payload: (
                    <Message.CustomContent>
                      <strong>This is strong text</strong>
                      <br />
                      Message content is provided as{" "}
                      <span
                        style={{
                          color: "red",
                        }}
                      >
                        {" "}
                        custom elements
                      </span>{" "}
                      from payload property
                    </Message.CustomContent>
                  ),
                }}
              >
                <Avatar
                  src={AVATAR_IMAGE}
                  name="Joe"
                />
              </Message>
            </MessageList>
            <MessageInput
              placeholder="Type message here"
            />
          </ChatContainer>
        </MainContainer>
      </div>
    </div>
  );
};

export default ChatUI;


컴포넌트와 데이터 분리하기

 

예시 코드에 있는 Message에서 messagedirection, avatar를 제외하고 모두 정리한다.

  <MessageList>
    <Message
      model={{
        message: "How are you?",
        direction: "incoming",
      }}
    >
      <Avatar src={AVATAR_IMAGE} name="bloodstrawberry" />
    </Message>
    <Message
      model={{
        message: "I'm fine, thank you, and you?",
        direction: "outgoing",                  
      }}
    />
    <Message
      model={{
        message: "I'm fine, too. thank you, and you?",
        direction: "incoming",
      }}
    >
      <Avatar src={AVATAR_IMAGE} name="bloodstrawberry" />
    </Message>
  </MessageList>

 

그리고 위의 컴포넌트에 있는 옵션들을 아래와 같이 분리한다.

const defaultMessage = [
  {
    model: {
      message: "How are you?",
      direction: "incoming",
    },
    avatar: {
      src: AVATAR_IMAGE,
      name: "bloodstrawberry",
    },
  },
  {
    model: {
      message: "I'm fine, thank you, and you?",
      direction: "outgoing",
    },
  },
  {
    model: {
      message: "I'm fine, too. thank you, and you?",
      direction: "incoming",
    },
    avatar: {
      src: AVATAR_IMAGE,
      name: "bloodstrawberry",
    },
  },
];

 

data를 이용해 Message 컴포넌트를 만들 수 있도록 메서드를 만든다.

  const getMessageComponent = (data) => {
    return data.map((item, index) => {
      return (
        <Message key={index} model={item.model}>
          {item.avatar ? (
            <Avatar src={item.avatar.src} name={item.avatar.name} />
          ) : null}
        </Message>
      );
    });
  };

 

이제 MessageList는 아래와 같이 간단히 변경된다.

  <MessageList>{getMessageComponent(defaultMessage)}</MessageList>

메시지 보내기

 

메시지는 MessageInput 컴포넌트에서 onSend를 이용하면 된다.

  <MessageInput
    placeholder="Type message here"
    onSend={handleSend}
  />

 

전체 메시지를 관리하기 위해 useState를 추가한다.

onSendinput이 들어오는 경우, 기존 메시지에서 새 메시지를 추가하도록 하였다.

  const [messages, setMessages] = useState(defaultMessage);

  const handleSend = (input) => {
    let newMessage = {
      model: {
        message: input,
        direction: "outgoing",
      },
    };

    setMessages([...messages, newMessage]);
  }

 

useStatemessages를 관리하였으므로 getMessageComponentmessages를 넘겨준다.

<MessageList>{getMessageComponent(messages)}</MessageList>

 

전체 코드는 다음과 같다.

import React, { useState } from "react";

import styles from "@chatscope/chat-ui-kit-styles/dist/default/styles.min.css";

import {
  MainContainer,
  ChatContainer,
  MessageList,
  Message,
  MessageInput,
  Avatar,
} from "@chatscope/chat-ui-kit-react";

const AVATAR_IMAGE =
  "https://img1.daumcdn.net/thumb/C428x428/?scode=mtistory2&fname=https%3A%2F%2Ftistory3.daumcdn.net%2Ftistory%2F4431109%2Fattach%2F3af65be1d8b64ece859b8f6d07fafadc";

const defaultMessage = [
  {
    model: {
      message: "How are you?",
      direction: "incoming",
    },
    avatar: {
      src: AVATAR_IMAGE,
      name: "bloodstrawberry",
    },
  },
  {
    model: {
      message: "I'm fine, thank you, and you?",
      direction: "outgoing",
    },
  },
  {
    model: {
      message: "I'm fine, too. thank you, and you?",
      direction: "incoming",
    },
    avatar: {
      src: AVATAR_IMAGE,
      name: "bloodstrawberry",
    },
  },
];

const getMessageComponent = (data) => {
  return data.map((item, index) => {
    return (
      <Message key={index} model={item.model}>
        {item.avatar ? (
          <Avatar src={item.avatar.src} name={item.avatar.name} />
        ) : null}
      </Message>
    );
  });
};

const ChatUI = () => {
  const [messages, setMessages] = useState(defaultMessage);

  const handleSend = (input) => {
    let newMessage = {
      model: {
        message: input,
        direction: "outgoing",
      },
    };

    setMessages([...messages, newMessage]);
  };

  return (
    <div>
      <div style={{ position: "relative", height: "500px" }}>
        <MainContainer>
          <ChatContainer>
            <MessageList>{getMessageComponent(messages)}</MessageList>
            <MessageInput placeholder="Type message here" onSend={handleSend} />
          </ChatContainer>
        </MainContainer>
      </div>
    </div>
  );
};

export default ChatUI;
반응형

댓글