Создайте анонимное приложение для чата с React & React bootstrap
Эта статья была впервые опубликована на Учебная страница CometChat.
Чтобы эффективно следовать этой статье, ожидается, что у вас есть следующее:
- Предварительное знание React. Вы можете использовать это ресурс чтобы освоиться с ним.
- Node.js и NPM установлены на вашем компьютере.
- Текстовый редактор или IDE. Рекомендуется код VS.
Введение
Разрешение пользователям общаться становится важной функцией для многих приложений. По моему опыту, чат сокращает дистанцию между вами и вашими клиентами и может привести к большему количеству конверсий, повышению вовлеченности; и, в конечном счете, больший успех для вашего бизнеса. Однако реализация чата может занять много времени.
В этом руководстве я рад показать вам, как можно создать эстетичный групповой чат с минимальным кодом, используя React, React Bootstrap и CometChat.
Вот предварительный просмотр того, что вы будете строить:
Вы можете погрузиться прямо в код или пройдите наш пошаговый учебник.
Создание нового проекта React
В этой статье, чтобы быстро создать новое приложение React, вы будете использовать один из очень популярных доступных инструментов — CLI-инструмент создания-реакции-приложения. Откройте терминал, перейдите в каталог, в котором вы обычно сохраняете свои проекты, и выполните следующую команду:
npx create-react-app react-anonymous-chat
После запуска команды CLI начнет процесс установки зависимостей по умолчанию для проекта React. В зависимости от скорости вашего интернета, это может занять пару минут. После настройки проекта откройте новый проект в предпочитаемом вами текстовом редакторе или IDE.
Установка зависимостей
Теперь, когда вы сформировали свое приложение, следующим шагом будет установка зависимостей, необходимых для вашего приложения чата. Для этой статьи вам понадобится следующее:
@cometchat-pro/chat
: этот модуль позволит нам подключиться к CometChat и начать отправлять и получать сообщения в режиме реального времени.react-bootstrap
: это библиотека пользовательского интерфейса, построенная на базе React и Core Bootstrap. Вы будете использовать его для оформления всего приложения в этой статье.react-router-dom
: вы будете использовать его для маршрутизации на стороне клиента.uuid
: этот модуль будет использоваться для создания уникальных идентификаторов.
Чтобы установить вышеуказанные модули, выполните следующие команды:
# move into your project directory
cd react-anonymous-chat
# install dependencies using npm
npm install @cometchat-pro/chat react-bootstrap react-router-dom uuid
Настройка
Чтобы начать использовать CometChat Pro SDK в только что созданном проекте React, вам потребуется учетная запись CometChat Pro. Если у вас нет учетной записи, вы можете быстро создать ее здесь.
После создания учетной записи перейдите на панель управления и создайте новое приложение под названием «реагировать-анонимно-чат». После создания нового приложения вы найдете идентификатор приложения рядом с названием вашего приложения. Если вы откроете свое приложение и перейдете в раздел «Ключи API», вы увидите ключ с областью действия fullAccess. Скопируйте его вместе с идентификатором приложения. Они понадобятся нам в ближайшее время.
Получите API-интерфейс CometChat
Далее создайте .env
файл в корне вашего проекта для хранения учетных данных вашего приложения. Будьте осторожны, чтобы не передать этот файл системе контроля версий! Это важно для защиты ваших секретов при публикации приложения. Вы можете легко создать файл, выполнив эту команду:
touch .env
Откройте файл и вставьте этот фрагмент:
REACT_APP_COMETCHAT_APIKEY=YOUR_API_KEY_GOES_HERE
REACT_APP_COMETCHAT_APPID=YOUR_APP_ID_GOES_HERE
Замените заполнители на ваш APP ID и API KEY с панели управления.
Поскольку ваши ключи теперь готовы, вы можете инициализировать CometChat
в index.js
файл, сгенерированный приложением Create React. Откройте свой index.js
файл и замените его этим фрагментом:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { CometChat } from '@cometchat-pro/chat';
CometChat.init(process.env.REACT_APP_COMETCHAT_APPID)
.then(() => {
console.log('Initialised CometChat');
})
.catch(() => {
console.log('Failed to Initialise CometChat');
});
ReactDOM.render(, document.getElementById('root'));
Прежде чем двигаться дальше, вам нужно импортировать Bootstrap в public/index.htm следующим образом:
<link
rel="stylesheet"
href="
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"
crossorigin="anonymous"
/>
Создание ваших компонентов
Ваше приложение будет состоять из трех компонентов: регистрации, домашней страницы и компонента чата. Компонент регистрации — это страница, которая позволит пользователям создавать новые учетные записи. Создайте папку с именем components
внутри src
каталог. Здесь вы будете добавлять свои компоненты.
Компонент регистрации
В этом компоненте вы создадите форму, которая поможет создавать новых пользователей в приложении. У пользователя будет UID
, адрес электронной почты и имя. UID
значение должно быть уникальным.
Создайте новый файл с именем Signup.js
Внутри файла добавьте эти импорты:
import React from 'react';
import Button from 'react-bootstrap/Button'
import Row from 'react-bootstrap/Row'
import Col from 'react-bootstrap/Col'
import Form from 'react-bootstrap/Form'
import Alert from 'react-bootstrap/Alert'
import Spinner from 'react-bootstrap/Spinner'
import { Redirect, Link } from 'react-router-dom'
Здесь вы импортируете некоторые компоненты из ядра react-bootstrap
компоненты, а также компоненты из react-router-dom
зависимость.
Затем вы определяете начальное состояние для вашего компонента регистрации в Signup.js
файл:
class Signup extends React.Component {
constructor(props) {
super(props);
this.state = {
uid: '',
name: '',
email: '',
UIDError: null,
errors: null,
redirect: false,
isLoading: false
};
}
//... other class methods
}
export default Signup;
Здесь вы определили состояние для хранения данных для формы регистрации и сообщений об ошибках. Вот конкретные функции каждого из объектов, объявленных в состоянии:
uid
: содержит текущее значение текста, введенного в поле формы имени пользователя.name
: содержит текущее значение имени пользователя в поле формы.email
: содержит текущее значение электронной почты пользователя в поле формы.UIDError
: этот объект будет отслеживать ошибки при проверке поля имени пользователя.errors
: здесь хранятся сообщения об ошибках при проверке других полей.
перенаправление: отслеживает успех отправки формы.isLoading
: используется для обеспечения визуальной обратной связи при использовании <Spinner />
составная часть.
UIDError
объект отслеживает ошибки в поле имени пользователя, в то время как errors
отслеживает ошибки в других полях. Они разделены, потому что поле имени пользователя не принимает пробелы и, как таковые, они не имеют одинаковой логики проверки.
После определения состояния вы создадите пользовательский интерфейс для представления текущего состояния вашего приложения. Добавьте этот метод рендеринга в свой Signup
учебный класс:
render() {
if (this.state.redirect) return ;
return (
<React.Fragment>
<Row
className="d-flex justify-content-center align-items-center w-100 mt-5"
style={{
minHeight: '100%'
}}
>
>Col>
{this.state.errors !== null && (
<Alert variant="danger">
<ul>
{this.showErrors().map(err => (
<li key={err}>{err</li>
))}
</ul>
</Alert>
)}
<Form onSubmit={this.handleSubmit}>
<Form.Group controlId='username'>
<Form.Label>User ID</Form.Label>
<Form.Control
required
type="text"
name="uid"
value={this.state.uid}
placeholder="Choose a username"
onChange={this.handleChange}
/>
{this.state.UIDError !== null && (
<Form.Control.Feedback
style={{ display: 'block' }}
type="invalid"
>
{this.state.UIDError}
</Form.Control.Feedback>
)}
</Form.Group>
<Form.Group controlId='display-name'>
<Form.Label>Name</Form.Label>
<Form.Control
required
type="text"
name="name"
value={this.state.name}
placeholder="What is your name?"
onChange={this.handleChange}
/>
</Form.Group>
<Form.Group controlId='email'>
<Form.Label>Email Address</Form.Label>
<Form.Control
required
type="email"
name="email"
value={this.state.email}
placeholder="Your email address"
onChange={this.handleChange}
/>
</Form.Group>
<Button
disabled={this.state.isLoading}
variant="primary"
type="submit"
className="btn-block"
>
{this.state.isLoading ? (
<>
<Spinner
as="span"
animation='grow'
size="sm"
role="status"
aria-hidden='true'
/>
Please wait...
</>
) : (
<span>Create My Account</span>
)}
</Button>
<p className="pt-3">
Already have an account? <Link to='/'>Login</Link>
</p>
</Form>
</Col>
</Row>
</React.Fragment>
);
}
Здесь, в этом фрагменте, вы объявили форму, в которой значения входных данных привязаны к состоянию, которое вы определили ранее. Форма содержит три ввода с собственной проверкой формы, за исключением ввода имени пользователя. Он также содержит <Redirect />
компонент и Link
который отображает домашний компонент там, где это необходимо.
Далее вы создадите три метода, используемые в render
метод, а именно: handleChange
, handleSubmit
а также showErrors
. Добавьте эти методы в свой Signup.js
файл:
handleChange = e => {
if (e.target.name === 'uid') {
const uid = e.target.value;
if (uid.indexOf(' ') > 0) {
this.setState(
{ UIDError: 'Username cannot contain white spaces' },
() => {
console.log(this.state.UIDError);
}
);
} else {
this.setState({ UIDError: null });
}
}
this.setState({ [e.target.name]: e.target.value });
};
handleSubmit = e => {
e.preventDefault();
const { uid, name, email } = this.state;
this.setState({ uid: '', name: '', email: '', isLoading: true });
fetch(' {
method: 'POST',
headers: {
'Content-Type': 'application/json',
appid: process.env.REACT_APP_COMETCHAT_APPID,
apikey: process.env.REACT_APP_COMETCHAT_APIKEY
},
body: JSON.stringify({
uid,
name,
email
})
})
.then(response => response.json())
.then(data => {
const error = data.error;
if (error) {
this.setState(
{
isLoading: false,
errors: { ...error.details }
},
() => {
this.showErrors();
}
);
return;
}
this.setState({
isLoading: false,
redirect: true
});
});
};
showErrors = () => {
const errors = this.state.errors;
let errorMessages = [];
if (errors !== null) {
for (const error in errors) {
errorMessages = [...errorMessages, ...errors[error]];
}
}
return errorMessages;
};
Если вы создаете производственное приложение, не следует хранить ключи во внешнем интерфейсе. Вместо этого ключи следует хранить на стороне сервера, чтобы закрытый ключ мог оставаться закрытым.
handleChange
метод обновляет значения всех полей ввода по мере ввода пользователем. Пользовательская проверка выполняется в поле имени пользователя, чтобы предотвратить имена пользователей без пробелов. handleSubmit()
метод делает POST
запрос к API создания аккаунта: с данными, введенными пользователем. В случае успеха вы будете перенаправлены на главную страницу.
showErrors
Метод используется для отображения ошибок.
Домашний компонент
Теперь, когда вы закончили с компонентом регистрации, вы теперь создадите домашний компонент. Этот компонент должен разрешить вход пользователей.
Создать новый файл Home.js
внутри /src/components
каталог. Внутри файла добавьте эти импорты:
import React from 'react';
import Button from 'react-bootstrap/Button';
import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col';
import Form from 'react-bootstrap/Form';
import Alert from 'react-bootstrap/Alert';
import Spinner from 'react-bootstrap/Spinner';
import { CometChat } from '@cometchat-pro/chat';
import { Redirect, Link } from 'react-router-dom';
Здесь вы импортировали компоненты, которые будете использовать так же, как и в компоненте регистрации. После этого добавьте этот фрагмент в класс:
class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
username: '',
user: null,
error: null,
redirect: false,
isLoading: false
};
}
//... other class methods
}
export default Home;
Здесь вы объявили начальное состояние для этого компонента. Это похоже на то, что вы делали в компоненте регистрации, за исключением того, что у вас есть имя пользователя и объект пользователя для хранения данных о вошедшем в систему пользователе.
После этого добавьте эти два метода в свой класс handleChange
а также handleSubmit
вот так:
handleChange = e => {
this.setState({ username: e.target.value });
};
handleSubmit = e => {
e.preventDefault();
const username = this.state.username;
this.setState({ username: '', isLoading: true });
CometChat.login(username, process.env.REACT_APP_COMETCHAT_APIKEY)
.then(user => {
this.setState({ redirect: true, user, isLoading: false });
localStorage.setItem('cometchat:authToken', user.authToken);
})
.catch(err => {
this.setState({ error: err.message, isLoading: false });
});
};
handleChange
метод обновляет значение поля ввода по мере ввода пользователем, в то время как handleSubmit
метод будет вызывать login
метод, предоставленный CometChat
. Чтобы сделать запрос на вход, ключ API, определенный в .env
файл передается вместе с именем пользователя.
При успешном входе в систему возвращаются данные пользователя и authToken
сохраняется для повторной аутентификации позже. Затем добавьте render
метод для этого компонента ниже handleSubmit
метод такой:
// other methods above...
render() {
if (this.state.redirect)
return (
<Redirect
to={{
pathname: '/chat',
user: this.state.user
}}
/>
);
return (
<React.Fragment>
<Row
className="d-flex justify-content-center align-items-center w-100 mt-5"
style={{
minHeight: '100%'
}}
>
<Col xs={10} sm={10} md={4} lg={4} className="mx-auto mt-5">
{this.state.error !== null && (
<Alert variant="danger">{this.state.error}</Alert>
)}
<Form onSubmit={this.handleSubmit}>
<Form.Group controlId='username'>
<Form.Label>Username</Form.Label>
<Form.Control
required
type="text"
value={this.state.username}
placeholder="Enter a Username"
onChange={this.handleChange}
/>
</Form.Group>
<Button
disabled={this.state.isLoading}
variant="primary"
type="submit"
className="btn-block"
>
{this.state.isLoading ? (
<>
<Spinner
as="span"
animation='grow'
size="sm"
role="status"
aria-hidden='true'
/>
Loading...
</>
) : (
<span>Login</span>
)}
</Button>
<p className="pt-3">
Don't have an account? <Link to='/signup'>Create One</Link>
</p>
</Form>
</Col>
</Row>
</React.Fragment>
);
}
В этом фрагменте у вас есть форма входа, чтобы использовать имя пользователя. Когда пользователь нажимает на Авторизоваться кнопку, вы принимаете пользовательский ввод и вызываете handleSubmit
метод, который вы определили ранее в этом компоненте. Если получен ответ об успешном завершении, пользователь перенаправляется в компонент чата, в противном случае отображается ошибка.
Компонент чата
Это компонент, в котором пользователь сможет просматривать сообщения и отправлять сообщения в группе чата. Сначала создайте новый Chat.js
файл в src/components
каталог. После этого добавьте эти импорты:
import React from 'react';
import { CometChat } from '@cometchat-pro/chat';
import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col';
import Container from 'react-bootstrap/Container';
import Form from 'react-bootstrap/Form';
import Button from 'react-bootstrap/Button';
import Navbar from 'react-bootstrap/Navbar';
import { Redirect } from 'react-router-dom';
import uuid from 'uuid';
После этого добавьте класс с состоянием в файл Chat.js следующим образом:
class Chat extends React.Component {
constructor(props) {
super(props);
this.state = {
redirect: false,
user: null,
receiverID: 'supergroup',
messageText: '',
messages: [],
authToken: null,
messageType: CometChat.MESSAGE_TYPE.TEXT,
receiverType: CometChat.RECEIVER_TYPE.GROUP
};
}
//... other class methods
}
export default Chat;
Здесь вам нужен массив сообщений для хранения всех сообщений, отправленных и полученных в группе. messageType
а также receiverType
объекты определяют тип сообщения, которое вы хотите прослушать, и для кого это сообщение. receiverID
объект используется для идентификации имени группы, в которой вы прослушиваете сообщения. Здесь вы использовали созданную для вас группу по умолчанию — супергруппа.
После этого добавьте render
метод для компонента чуть ниже конструктора следующим образом:
render() {
if (this.state.redirect) return <Redirect to='/' />;
return (
<div
className="bg-light page"
style={{ height: '100vh', overflowX: 'hidden' }}
>
<Row>
<Col>
<Container>
<div className="d-flex align-items-center justify-content-between">
<h3 className="text-center py-3 d-inline">
React Anonymous Chat
</h3>
<Button onClick={e => this.logout()} variant="outline-primary">
Logout
</Button>
</div>
<ul className="list-group" style={{ marginBottom: '60px' }}>
{this.state.messages.length > 0 ? (
this.state.messages.map(msg => (
<li className="list-group-item" key={uuid()}>
<strong>{msg.sender.name}</strong>
<p>{msg.text}</p>
</li>
))
) : (
<div className="text-center mt-5 pt-5">
<p className="lead text-center">Fetching Messages</p>
</div>
)}
</ul>
</Container>
</Col>
</Row>
<Navbar fixed='bottom'>
<Container>
<Form
inline
className="w-100 d-flex justify-content-between align-items-center"
onSubmit={this.sendMessage}
>
<Form.Group style={{ flex: 1 }}>
<Form.Control
value={this.state.messageText}
style={{ width: '100%' }}
required
type="text"
placeholder="Type Message here..."
onChange={this.handleChange}
/>
</Form.Group>
<Button variant="primary" type="submit">
Send
</Button>
</Form>
</Container>
</Navbar>
</div>
);
}
В этом методе рендеринга у вас есть <Redirect />
компонент, который перенаправляет на домашний компонент, когда нет зарегистрированного пользователя. У вас также есть окно сообщений, в котором отображаются все сообщения, отправленные и полученные в группе, и, наконец, у вас есть форма для обработки отправки сообщений.
Есть несколько методов, которые вызываются здесь, пока не беспокойтесь, вы скоро определите эти методы. Теперь, когда вы создали пользовательский интерфейс для компонента чата, следующим шагом будет отображение сообщений пользователю. Вы сделаете это, как только компонент будет смонтирован. В твоей Chat.js
файл, добавьте этот метод:
componentDidMount() {
this.setState({ user: this.props.location.user });
this.getUser();
this.receiveMessages();
}
Это функция обратного вызова, предоставляемая React. В этом методе вы будете получать информацию о пользователе и прослушивать новые сообщения в группе. Теперь добавьте getUser()
метод такой:
getUser = () => {
CometChat.getLoggedinUser().then(
user => {
this.joinGroup();
},
error => {
const authToken = localStorage.getItem('cometchat:authToken');
if (authToken !== null) {
this.setState({ authToken }, () => {
this.reAuthenticateUserWithToken(this.state.authToken);
});
} else {
this.setState({ redirect: true });
}
}
);
};
В этом методе вы получаете зарегистрированного пользователя и присоединяетесь к группе, используя joinGroup()
метод . Если при получении пользователя возникает ошибка, authToken
Хранится в localStorage
служит запасным вариантом для повторной аутентификации пользователя. joinGroup()
метод еще не определен. Создайте метод внутри вашего Chat.js
выглядеть так:
joinGroup = () => {
const GUID = this.state.receiverID;
const password = '';
const groupType = CometChat.GROUP_TYPE.PUBLIC;
CometChat.joinGroup(GUID, groupType, password).then(
group => {},
error => {
if (error.code === 'ERR_ALREADY_JOINED') {
this.reAuthenticateUserWithToken();
}
}
);
};
Здесь, в этом методе, пользователь подписан на эту группу, и теперь он может отправлять и получать сообщения из этой группы. Так же fetchMessages()
метод вызывается для получения предыдущих сообщений, когда пользователь успешно присоединяется к группе. Добавить fetchMessages()
метод тоже:
fetchMessages = () => {
const GUID = this.state.receiverID;
const limit = 30;
const messagesRequest = new CometChat.MessagesRequestBuilder()
.setGUID(GUID)
.setLimit(limit)
.build();
messagesRequest.fetchPrevious().then(
messages => {
const textMessages = messages.filter(msg => msg.type === 'text');
this.setState({ messages: [...textMessages] });
this.scrollToBottom();
},
error => {
console.log('Message fetching failed with error:', error);
}
);
};
Это извлекает предыдущие сообщения, отправленные группе. Чтобы пользователи могли видеть самые новые сообщения, scrollToBottom()
метод называется. Добавить scrollToBottom()
метод для вашего класса следующим образом:
scrollToBottom = () => {
const page = document.querySelector('.page');
page.scrollTop = page.scrollHeight;
};
Теперь, когда вы можете получать предыдущие сообщения, пришло время разрешить пользователям также отправлять новые сообщения. Для этого сначала нужно создать handleChange()
метод для обновления состояния всякий раз, когда пользователь вводит новое сообщение. Добавьте этот метод в свой компонент класса:
handleChange = e => {
this.setState({ messageText: e.target.value });
};
После этого вы добавляете sendMessage
метод такой:
sendMessage = e => {
e.preventDefault();
const { receiverID, messageText, messageType, receiverType } = this.state;
const textMessage = new CometChat.TextMessage(
receiverID,
messageText,
messageType,
receiverType
);
CometChat.sendMessage(textMessage).then(
message => {
this.setState({ messageText: '' });
const oldMessages = [...this.state.messages];
const filtered = oldMessages.filter(msg => msg.id !== message);
this.setState({ messages: [...filtered, message] });
this.scrollToBottom();
},
error => {
console.log('Message sending failed with error:', error);
}
);
};
Этот метод вызывается, когда форма в render()
метод представлен. После sendMessage
метод ComeChat
вызывается, поле ввода очищается и новые сообщения будут добавлены в массив сообщений. Новые сообщения также фильтруются в случае дублирования, и, наконец, scrollToBottom()
вызывается, чтобы сосредоточить внимание на новых сообщениях.
Второй метод, который вы вызвали в componentDidMount
метод был receiveMessages
. Теперь создайте метод внутри вашего класса:
receiveMessages = () => {
const listenerID = 'supergroup';
CometChat.addMessageListener(
listenerID,
new CometChat.MessageListener({
onTextMessageReceived: textMessage => {
const oldMessages = this.state.messages;
oldMessages.push(textMessage);
this.setState(
{
messages: [...oldMessages]
},
() => this.scrollToBottom()
);
}
})
);
};
Поскольку вас интересуют только текстовые сообщения, только onTextMessageReceived
используется обработчик. При получении новых сообщений массив сообщений обновляется для отображения сообщений в режиме реального времени.
После этого вам нужно добавить метод выхода из системы, чтобы пользователи, прошедшие проверку подлинности, могли выйти из приложения. Добавьте метод выхода в Chat.js
файл так:
logout = () => {
CometChat.logout().then(() => {
localStorage.removeItem('cometchat:authToken');
this.setState({ redirect: true });
});
};
Когда пользователь нажимает кнопку выхода, вы вызываете logout()
метод, затем вы сбрасываете localStorage
и перенаправить пользователя на главную страницу.
Теперь, когда вы определили свои компоненты, вы должны обновить App.js
файл с маршрутами. Откройте свой App.js
файл и замените его на это:
import React from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import Home from "./components/Home";
import Chat from "./components/Chat";
import Signup from "./components/Signup";
function App() {
return (
<Router>
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/signup" component={Signup} />
</Switch>
</Router>
);
}
export default App;
Итак, вы успешно завершили создание своего приложения. Запустите эту команду в корневом каталоге вашего приложения:
npm start
У вас должно получиться что-то похожее на то, что вам показывали ранее.
Вывод
В этой статье вы узнали, как создать анонимный чат с помощью React, React Bootstrap и CometChat Pro. Теперь вы можете удобно интегрировать групповые чаты в приложения React. Что касается CometChat Pro SDK, то существует множество других функций, не описанных в этой статье. Не стесняйтесь расширять это, углубляясь в документация.