Автор оригинала: FreeCodeCamp Community Member.
Live Chat – это метод поддержки клиентов с проверенной записью. Это быстро и эффективно, так как один агент может помочь многим клиентам одновременно. Лучше всего, тем быстрее вы можете ответить на вопросы клиента во время процесса покупки, тем более вероятно, что человек должен купить.
Итак, как вы интегрируете живой чат в ваше приложение React?
В этом руководстве я собираюсь показать вам, как интегрировать функцию Live Chat в ваше приложение React без беспокойства о сохранении собственного сервера чата и архитектуры.
Вот предварительный просмотр того, что мы будем строить:
Чтобы включить наше приложение чата, мы будем использовать Comethat Pro.
COMCHAT PRO – мощная коммуникационная API, которая позволяет добавлять функции чата в ваше приложение. С помощью легких интеграций и прозрачной документации вы сможете добавить функцию в прямом эфире в вашу приложение всего несколькими строками кода, как вы скоро посмотрите. Если вы хотите следить, вы можете создать бесплатную учетную запись здесь Отказ
В дополнение к Comethat мы будем использовать следующие технологии:
- Создать приложение React
- reac-chat-widget
- выражать
- Загрузка
- Axios.
- React-MD (только спиннер компонента)
Я призываю вас следовать, но если вы предпочитаете пропустить к коду, вы можете найти полный код для этого приложения на Github Отказ
Первые вещи сначала создайте свое приложение Comethat
Чтобы включить приложение вашего чата, вы будете использовать Chetchat. Прежде чем вы сможете интегрировать CHETCHAT, вы должны сначала создать приложение Cometchat.
Чтобы создать приложение Comethat, перейдите на панель инструментов Comethat (если у вас нет бесплатной учетной записи Comethat, уже сейчас хорошее время для Зарегистрируйтесь ) и нажмите кнопку +.
Я позвонил в мою приложение «React-Chat-Widget», но вы можете позвонить вам как угодно.
У нас будет два типа пользователей, подключаемых к нашему чату: клиенты, которые открывают виджет чата и один агент поддержки, который будет получать доступ к чату и отвечать на запросы с помощью приборной панели. Пользователи – фундаментальная концепция в Chetchat, которую вы можете прочитать больше о здесь Отказ
Поскольку у нас, скорее всего, у нас будет много клиентов, для каждого клиента, который подключается к нашему чату, нам нужно будет динамически создавать пользователь Comethat. Однако потому, что будет только один агент, мы можем создать пользователь «агента» заранее с помощью приборной панели.
Для этого нажмите Explore, затем отправляйтесь на вкладку «Пользователи». Здесь вы можете нажать Создать пользователь:
Для идентификатора пользователя я написал «ecommerce-агент» и для имени, я написал «Демо-агент». Я рекомендую вам использовать те же значения, если вы следуете. В любом случае, обратите внимание на идентификатор пользователя, потому что вам нужно будет ссылаться на это позже.
Перед тем, как мы перейдем к приборной панели и включенным в код, мы должны создать полный ключ доступа Comethat.
На той же странице выберите вкладку клавиш API, затем создайте клавишу API:
Я позвонил в мой ключ «ract-chat-API», но это не имеет значения, что вы пишете здесь.
Обратите внимание, что ваш ключ API и идентификатор приложения, потому что, как и идентификатор пользователя агента, вам понадобятся они как позже.
Настройка экспресс
На предыдущем шаге мы создали полный ключ доступа, который мы можем использовать для динамическими пользователей CHETCHAT. Хотя мы могли бы сделать это на клиенте, что означало бы совместное использование нашего закрытого ключа полного доступа на публике, что нет.
Чтобы избежать этой проблемы, мы создадим простой экспресс-сервер, который:
- Создает пользователь Comethat, используя полный ключ доступа
- Возвращает токены аутентификации (больше на это позже)
- Возвращает список пользователей Comethat, для использования позже в приборной панели
Хорошо, давайте начнем.
Во-первых, создайте новый пустой каталог для вашего Express App и запустите `npm init -y`:
mkdir react-express-chat-widget cd react-express-chat-widget npm init -y
Далее установите Express and Axios:
npm install express axios
Затем в файле под названием Sever.js
вставить:
const express = require('express'); const axios = require('axios'); const app = express(); // enter CometChat Pro configurations here const appID = '{appID}'; const apiKey = '{apiKey}'; const agentUID = '{agentUID}'; const url = 'https://api.cometchat.com/v1'; const headers = { 'Content-Type': 'application/json', appid: appID, apikey: apiKey, };
В приведенном выше файле мы:
- Храните наши прикладные учетные данные и идентификатор пользователя агента, который мы создали ранее
- Определите API Cometchat
URL
Для удобного доступа - Создать
Заголовки
объект с нашимAppID
иApikey
Отказ Мы отправим этот заголовок с каждым запросом к Comethat
В том же файле, давайте теперь определим маршрут для обработки создания новых пользователей Comethat.
Чтобы создать новый пользователь, нам нужно отправить запрос на сообщение с UID и именем для пользователя.
В этом руководстве мы будем труднодобывать то же имя для всех клиентов – мы позвоним каждому клиенту «Клиент» – но UID должен быть уникальным. Для UID мы можем использовать Новая дата (). Получить ()
генерировать случайный идентификатор.
Добавьте следующий код в server.js
:
app.get('/api/create', (req, res) => { // data for new user const data = { // you can use your own logic to generate random UID and name // only uid has to be unique uid: new Date().getTime(), name: 'customer', }; axios .post(`${url}/users`, JSON.stringify(data), { headers, }) .then(response => { // user is created, fetch auth token requestAuthToken(response.data.data.uid) .then(token => { console.log('Success:' + JSON.stringify(token)); // token is returned to client res.json(token); }) .catch(error => console.error('Error:', error)); }) .catch(error => console.error('Error:', error)); }); // this function will fetch token const requestAuthToken = uid => { return new Promise((resolve, reject) => { axios .post(`${url}/users/${uid}/auth_tokens`, null, { headers, }) .then(response => { console.log('New Auth Token:', response.data); resolve(response.data.data); }) .catch(error => reject(error)); }); };
Когда этот маршрут называется, Express Will:
- Отправить сообщение запроса на https://api.cometchat.com/v1/users/ С правильными
Заголовки
и информация о новом пользователе - Получить токен аутентификации для нового пользователя
- И, наконец, верните его к абонеру
Мы также создали функцию под названием ЗапросАутекен
Чтобы помочь с выбором токена аутентификации.
Далее в том же файле давайте создадим маршрут аутентификации, мы можем позвонить в создание токенов для возврата пользователей:
//... app.get('/api/auth', (req, res) => { const uid = req.query.uid; // if you have your own login method, call it here. // then call CometChat for auth token requestAuthToken(uid) .then(token => { console.log('Success:' + JSON.stringify(token)); res.json(token); }) .catch(error => console.error('Error:', error)); }); //...
Наконец, давайте создадим функцию, чтобы вернуть список пользователей, исключая агента.
Позже мы назовем эту конечную точку с помощью приборной панели позже, чтобы показать список пользователей, которые агент может говорить с (конечно, агент не хочет говорить с собой, поэтому мы отфильтровали их из списка):
//... app.get('/api/users', (req, res) => { axios .get(`${url}/users`, { headers, }) .then(response => { const { data } = response.data; const filterAgentData = data.filter(data => { // filter agent out from the list of users return data.uid !== agentUID; }); res.json(filterAgentData); }) .catch(error => console.error('Error:', error)); }); //...
В самом нижней части server.js
Запустите сервер:
const PORT = process.env.PORT || 5000; app.listen(PORT, () => { console.log(`Listening on port ${PORT}`); });
Если вы следуете, это то, что server.js
должен выглядеть сейчас:
const express = require('express'); const axios = require('axios'); const app = express(); const appID = '{appID}'; const apiKey = '{apiKey}'; const agentUID = '{agentUID}'; const url = 'https://api.cometchat.com/v1'; const headers = { 'Content-Type': 'application/json', appid: appID, apikey: apiKey, }; app.get('/api/create', (req, res) => { const data = { uid: new Date().getTime(), name: 'customer', }; axios .post(`${url}/users`, JSON.stringify(data), { headers, }) .then(response => { requestAuthToken(response.data.data.uid) .then(token => { console.log('Success:' + JSON.stringify(token)); res.json(token); }) .catch(error => console.error('Error:', error)); }) .catch(error => console.error('Error:', error)); }); app.get('/api/auth', (req, res) => { const uid = req.query.uid; requestAuthToken(uid) .then(token => { console.log('Success:' + JSON.stringify(token)); res.json(token); }) .catch(error => console.error('Error:', error)); }); const requestAuthToken = uid => { return new Promise((resolve, reject) => { axios .post(`${url}/users/${uid}/auth_tokens`, null, { headers, }) .then(response => { console.log('New Auth Token:', response.data); resolve(response.data.data); }) .catch(error => reject(error)); }); }; app.get('/api/users', (req, res) => { axios .get(`${url}/users`, { headers, }) .then(response => { const { data } = response.data; const filterAgentData = data.filter(data => { return data.uid !== agentUID; }); res.json(filterAgentData); }) .catch(error => console.error('Error:', error)); }); const PORT = process.env.PORT || 5000; app.listen(PORT, () => { console.log(`Listening on port ${PORT}`); });
В окне терминала запустите Node Server.js
И посмотрите на сообщение, которое говорит «Прослушивание порта 5000». Теперь будет хорошее время для проверки конечных точек с завитым или Почтальон Но мы доверяем, они работают и переходят на клиента.
Настройка приложения RACT
Внутри вашего каталога запустите NPX Create-React-App
К услугам гостей новое действие Action:
npx create-react-app client
Структура вашей папки должна выглядеть так:
|-- express-react-chat-widget |-- package-lock.json |-- package.json |-- server.js |-- client |-- .gitignore |-- package-lock.json |-- package.json |-- public |-- src
С приложением React на месте навигации к клиент
Справочник Установите следующие модули:
cd client npm install @cometchat-pro/chat react-chat-widget react-router-dom bootstrap react-md-spinner
Приложение Create React React действительно полезна для загрузки приложения React React, но он также генерирует много файлов, которые нам не нужно (тестовые файлы и т. Д.).
Прежде чем мы прыгаем в код, удалите все в Клиент/SRC
Справочник – мы начнем с нуля.
Для начала создать config.js
Файл с идентификатором вашего приложения и Agent UID внутри:
// client/src/config.js const config = { appID: '{appID}', agentUID: '{agentUID}', } export default config;
Это немного котельной, мы можем использовать для ссылки на наши учетные данные Comethat в любом месте.
Пока мы имеем дело с котельной, давайте также возьму эту возможность создать index.csss
файл:
body { margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } .message { overflow: hidden; } .balon1 { float: right; background: #35cce6; border-radius: 10px; } .balon2 { float: left; background: #f4f7f9; border-radius: 10px; }
Мы будем ссылаться на это позже с помощью приборной панели.
Теперь в файле под названием index.js
Вставьте следующее:
import React from 'react'; import ReactDOM from 'react-dom'; import 'bootstrap/dist/css/bootstrap.css'; import './index.css'; import App from './App'; import { CometChat } from '@cometchat-pro/chat'; import config from './config'; CometChat.init(config.appID) ReactDOM.render(, document.getElementById('root'));
Здесь мы импортируем Bootstrap, Comethat и файл конфигурации, который мы только что создали перед инициализацией CHETCHAT и рендеринга нашего Приложение
Отказ
Если вы следуете, вы заметили, что мы не определили Приложение
И все же – давайте сделаем это сейчас.
В файле под названием App.js
:
import React from 'react'; import { BrowserRouter as Router, Route, Link } from 'react-router-dom'; import Client from './Client'; import Agent from './Agent'; const App = () => { return (); } export default App;
- Client Home
- Agent Dashboard
Здесь мы определяем два маршрута:
-
/
или«Клиент Главная»
Маршрут для клиента общаться с агентом - И
/агент
или«Агент приборной панели»
Маршрут для быстрого и удобного доступа к приборной панели
Давайте сначала решаем компонент с клиентом. Мы назовем это клиентский компонент.
Создание клиентского компонента
Наш клиентский компонент будет иметь два основных обязанности:
- Создайте новый пользователь Comethat через наш экспресс-сервер, когда клиент сначала подключается
- Отправить и получать сообщения в режиме реального времени.
Создайте файл под названием Client.js
и вставьте следующее:
// Client.js import React, {Component} from 'react'; import { Widget, addResponseMessage, addUserMessage, dropMessages } from 'react-chat-widget'; import { CometChat } from '@cometchat-pro/chat'; import config from './config'; import 'react-chat-widget/lib/styles.css'; const agentUID = config.agentUID; const CUSTOMER_MESSAGE_LISTENER_KEY = "client-listener"; const limit = 30; class Client extends Component { componentDidMount() { addResponseMessage('Welcome to our store!'); addResponseMessage('Are you looking for anything in particular?'); } render() { return (); } createUser = async () => { const response = await fetch(`/api/create`) const result = await response.json() return result; } handleNewUserMessage = newMessage => { console.log(`New message incoming! ${newMessage}`); var textMessage = new CometChat.TextMessage( agentUID, newMessage, CometChat.MESSAGE_TYPE.TEXT, CometChat.RECEIVER_TYPE.USER ); let uid = localStorage.getItem("cc-uid"); if (uid === null) { // no uid, create user this.createUser().then( result => { console.log('auth token fetched', result); localStorage.setItem("cc-uid",result.uid) // do login CometChat.login(result.authToken) .then(user => { console.log("Login successfully:", { user }); CometChat.sendMessage(textMessage).then( message => { console.log('Message sent successfully:', message); }, error => { console.log('Message sending failed with error:', error); } ); // create listener CometChat.addMessageListener( CUSTOMER_MESSAGE_LISTENER_KEY, new CometChat.MessageListener({ onTextMessageReceived: message => { console.log("Incoming Message Log", { message }); addResponseMessage(message.text); } }) ); }) }, error => { console.log('Initialization failed with error:', error); }) } else { // we have uid, do send CometChat.sendMessage(textMessage).then( message => { console.log('Message sent successfully:', message); }, error => { console.log('Message sending failed with error:', error); } ); } }; componentWillUnmount() { CometChat.removeMessageListener(CUSTOMER_MESSAGE_LISTENER_KEY); CometChat.logout(); dropMessages(); } } export default Client;
WOAH, это много нового кода. Давайте сломаемся.
оказывать
Функция достаточно проста, она в основном сводится к отображению React-Chat-Widget Отказ
Большая часть кода предназначена для обработки нового сообщения, отправленного клиентом в функции, называемой Handlenwusermessage
Отказ
В двух словах мы сначала проверяем, существует ли UID клиента в LocalStorage. Если это так, мы будем использовать этот UID, чтобы войти в систему пользователя и отправлять сообщения. В противном случае мы называем CreateUser ()
и используйте возвращенное значение для входа в систему. Это Createuser
Функция вызывает конечную точку, которую мы определили ранее в руководстве.
Наконец, в функции React Lifecycle называется ComponentWillunmount
Мы не помните, что убрать слушатель сообщения.
Прежде чем двигаться дальше, вот немного наконечника: в вышеуказанном коде, а не набрав URL-адрес сервера и порту («Localhost: 5000/пользователи»
или что-то в этом роде) на нашем интерфейсе мы можем вместо этого добавить прокси Вариант для Package.json
Отказ Это позволит нам написать /пользователи "
вместо //localhost: 5000/пользователи"
:
"browserslist": [ ">0.2%", "not dead", "not ie <= 11", "not op_mini all" ], "proxy": "http://localhost:5000"
Вот что должно выглядеть приложение:
Как видите, вы можете отправлять и получать сообщения, но если мы обновляем нашу страницу, сообщения чата все исчезнут, и это не хорошо.
Чтобы решить эту проблему, мы настроим ComponentDidmount
Метод для поиска клиентов UID в LocalStorage
Так что, когда клиенты обновляют страницу, они могут продолжать общаться от того места, где они остановились.
После найден, мы будем использовать этот UID, чтобы инициировать цепочку методов Войти, извлечь предыдущие сообщения и Создать слушатель для входящих сообщений.
componentDidMount() { addResponseMessage('Welcome to our store!'); addResponseMessage('Are you looking for anything in particular?'); let uid = localStorage.getItem("cc-uid"); // check for uid, if exist then get auth token if ( uid !== null) { this.fetchAuthToken(uid).then( result => { console.log('auth token fetched', result); // SDK login CometChat.login(result.authToken) .then( user => { console.log("Login successfully:", { user }); // listen to incoming message and fetch previous messages this.createMessageListener(); this.fetchPreviousMessages(); }) }, error => { console.log('Initialization failed with error:', error); } ); } } // The functions used above fetchAuthToken = async uid => { const response = await fetch(`/api/auth?uid=${uid}`) const result = await response.json() return result; } createMessageListener = () => { CometChat.addMessageListener( CUSTOMER_MESSAGE_LISTENER_KEY, new CometChat.MessageListener({ onTextMessageReceived: message => { console.log("Incoming Message Log", { message }); addResponseMessage(message.text); } }) ); } fetchPreviousMessages = () => { var messagesRequest = new CometChat.MessagesRequestBuilder() .setUID(agentUID) .setLimit(limit) .build(); messagesRequest.fetchPrevious().then( messages => { console.log("Message list fetched:", messages); // add messages to the widget chat bubbles messages.forEach( message => { if(message.receiver !== agentUID){ addResponseMessage(message.text); } else { addUserMessage(message.text) } }); }, error => { console.log("Message fetching failed with error:", error); } ); }
Теперь, если мы обновляем нашу страницу, приложение попытается войти в Cometchat и автоматически извлеките предыдущие сообщения, искал нашего клиента UID из LocalStorage
Отказ Хорошая вещь!
Хотя есть еще небольшая проблема. Как это выдерживается прямо сейчас, для агента все еще нет никакого способа ответить на сообщения клиента.
Мы решим эту проблему, создав приборную панель агента, где наш агент может просматривать и отвечать сообщениям чата от клиентов.
Мы закончили с Client.js
Файл, так что вы можете схватить кофе, прежде чем перейти к коду Agent.js
Файл ☕.
Создание компонента агента
Основная функция приборной панели агентов состоит в том, чтобы захватить всех клиентов из Comethat Pro и отображать любое входящее сообщение от нового клиента в список клиентов в чате для агентов, чтобы нажать и ответить. Основная функциональность очень похожа на клиента:
С COMCTHAT вы можете легко создать несколько агентов, но чтобы все могли простые и избегать управления пользователями, у нас только один агент, который мы создали ранее.
Создайте компонент под названием Agent.js
и установить начальное состояние:
import React, {Component} from 'react'; import {CometChat} from '@cometchat-pro/chat'; import MDSpinner from "react-md-spinner"; import config from './config'; const agentUID = config.agentUID; const AGENT_MESSAGE_LISTENER_KEY = 'agent-listener' const limit = 30; class Agent extends Component { state = { customers: [], selectedCustomer: '', chat: [], chatIsLoading: false, customerIsLoading:true } }
В том же файле создайте ComponentDidmount
Метод:
componentDidMount(){ this.fetchAuthToken(agentUID).then( authToken => { console.log('auth token fetched', authToken); CometChat.login(authToken) .then( user => { console.log("Login successfully:", { user }); // after login, fetch all users // put them into customer state this.fetchUsers().then(result => { this.setState({ customers: result, customerIsLoading: false }) }); CometChat.addMessageListener( AGENT_MESSAGE_LISTENER_KEY, new CometChat.MessageListener({ onTextMessageReceived: message => { let {customers, selectedCustomer, chat} = this.state; console.log("Incoming Message Log", { message }); // check incoming message // if from the same customer agent is currently chatting // push a new chat item into chat state if(selectedCustomer === message.sender.uid){ chat.push(message); this.setState({ chat }) } else { // if new customer, push a new customer into customer state let aRegisteredCustomer = customers.filter( customer => { return customer.uid === message.sender.uid }); if(!aRegisteredCustomer.length){ customers.push(message.sender) this.setState({ customers }) } } } }) ); }) }, error => { console.log('Initialization failed with error:', error); } ); } fetchUsers = async () => { const response = await fetch(`/api/users`) const result = await response.json() return result; }
В приведенном выше Кодексе много происходит, вот вскрытие, чтобы помочь вам понять:
- Во-первых, мы автоматически войти в систему нашего агента и извлеките всех пользователей для агента общаться с сервера
- Далее мы создаем прослушиватель входящего сообщения. Каждый раз, когда сообщение получено в выбранном разговоре, мы толкаем его в чате, который, в свою очередь, обновляет пользовательский интерфейс
- Если входящее сообщение не от выбранного в данный момент разговора, мы проверяем, от того, от того, от того, от того, от того, от того, является ли новое сообщение от зарегистрированного клиента. Если нет, мы толкаем этого нового клиента к государству клиента.
Вы, вероятно, узнаете Express API, мы создаем, чтобы получить список зарегистрированных пользователей. Мы используем это, чтобы заполнить список пользователей на левой стороне приборной панели. Мы разместим список на левую руку, используя комбинацию загрузчиков и index.csss
файл, который мы определили ранее.
Далее давайте создадим функцию рендера. Он будет представлять интерфейс разговора, в стиле загрузки. Чтобы сделать код проще следовать, мы отделим Клиентлист
и Чатбокс
в свои собственные компоненты, которые вы можете определить в том же файле:
render() { return() }Customer List
{/* The CustomerList component */}Who you gonna chat with?
{/* The ChatBox component */}
Чатбокс
составная часть:
class ChatBox extends Component { render(){ const {chat, chatIsLoading} = this.props; if (chatIsLoading) { return () } else { // simple mapping of array from props return ( { chat .map(chat =>) } } }) }{chat.text}
Клиентлист
составная часть:
class CustomerList extends Component { render(){ const {customers, customerIsLoading, selectedCustomer} = this.props; if (customerIsLoading) { return () } else { // simple mapping of array from props return (
-
{
customers
.map(customer =>
- this.props.selectCustomer(customer.uid) }> {customer.name} ) }
Это составляет основу для нашего UI, но мы все еще не можем отправлять сообщения.
Для отправки сообщений мы должны создать обработчик, когда агент подает новое сообщение. Как отправлять сообщения, должны быть вам знакомыми сейчас, потому что мы сделаем то же самое SendMessage
Позвоните, что мы сделали в клиентском компоненте.
handleSubmit = event => { event.preventDefault(); let message = this.refs.message.value; var textMessage = new CometChat.TextMessage( this.state.selectedCustomer, message, CometChat.MESSAGE_TYPE.TEXT, CometChat.RECEIVER_TYPE.USER ); CometChat.sendMessage(textMessage).then( message => { let {chat} = this.state; console.log('Message sent successfully:', message); chat.push(message); this.setState({ chat }) }, error => { console.log('Message sending failed with error:', error); } ); this.refs.message.value=''; }
Мы также захочем позволить агенту увидеть исторические сообщения, такие как мы сделали для клиента:
selectCustomer = uid => { this.setState({ selectedCustomer: uid }, ()=> {this.fetchPreviousMessage(uid)}) } fetchPreviousMessage = uid => { this.setState({ hat: [], chatIsLoading: true }, () => { var messagesRequest = new CometChat.MessagesRequestBuilder() .setUID(uid) .setLimit(limit) .build(); messagesRequest.fetchPrevious().then( messages => { console.log("Message list fetched:", messages); this.setState({ chat: messages, chatIsLoading: false }) }, error => { console.log("Message fetching failed with error:", error); } ); }); }
Не забудьте удалить слушатель сообщения, когда компонент размонтирует:
componentWillUnmount(){ CometChat.removeMessageListener(AGENT_MESSAGE_LISTENER_KEY); CometChat.logout(); }
Если у вас есть какие-либо проблемы, вы можете ссылаться на полную Агент Файл здесь на Github.
Проверьте последний продукт:
Если вам интересно, откуда пришли эти пользователи Superhero, они автоматически создаются Comethat Pro, когда вы создаете новое приложение. Не забудьте удалить их перед использованием приложения в производстве.
Теперь и агент поддержки, и ваши клиенты готовы пообщаться друг с другом. Вы можете открыть клиентский домашний и агентную панель инструментов в отдельных окнах и попробовать.
Поздравляю!
Заключение
Мы сделали наш собственный виджет Live Chat для приложения React Application, и вообще не было времени! Действительно, Comethat Pro позволяет отправлять и получать сообщение, написав только несколько строк кода. Вам не нужно иметь дело с созданием собственного сервера чата и архитектуры. Он также имеет больше возможностей, чем просто виджет чата.
Если вы хотите расширить это приложение, попробуйте позволить клиентам отправить СМИ с Chetchat.
P.S: Если вы изо всех сил пытаетесь научиться реагировать, вы можете найти React Reptived. Большая помощь. Проверьте это здесь !