Пишем собственный чат на React за 10 простых шагов
Рассказываем, как создать собственный чат на React.js с помощью Charset SDK: от создания компонентов до работы со сторонним API.
Шаг 1: раскладываем интерфейс на компоненты
Так как Реакт – компонентный фреймворк, первое, что нам нужно сделать, это представить чат на React как набор элементов.
Начнем с создания корневого компонента – своеобразного холдера для всех остальных элементов приложения:
Красный прямоугольник вокруг макета – корневой элемент, назовем его App.
Теперь нужно разобраться с вопросом: какие дочерние элементы должен содержать чат на React.js? В нашем случае, есть смысл создать три дочерних элемента, которые мы назовем следующим образом:
- Title
- MessageList
- SendMessageForm
Выделим их на макете:
При построении компонентного приложения, необходимо постоянно спрашивать себя: какие еще компоненты может содержать интерфейс? Таким образом, можно создавать более простые составные части для будущих сложных компонентов.
Шаг 2: настраиваем кодовую базу
Для знакомства с фреймворком воспользуемся самым простым путем сборки приложения: просто создадим файл index.html, к которому подключим необходимые библиотеки и код.
Кроме самого Реакта, мы импортируем Charset SDK и Babel, который необходим для преобразования JSX.
Откройте готовый проект в новой вкладке и попробуйте поиграть с кодом, если будете испытывать трудности с пониманием туториала.
Также по ссылке проект можно скачать в виде архива и развернуть на локальном сервере.
Шаг 3: создаем корневой компонент
Когда все необходимые файлы подключены, можно приступать к написанию компонентов. Они будут создаваться в файле index.js.
Начнем с создания основного компонента App. App станет единственным «умным» компонентом нашей системы, так как он будет обрабатывать данные и общаться с API. Его вид в базовом виде (без логики):
class App extends React.Component { render() { return ( <div className="app"> <Title /> <MessageList /> <SendMessageForm /> </div> ) } }
Сейчас App только рендерит три дочерних компонента: <Title>,<MessageList>, и <SendMessageForm>.
Сообщения чата будут храниться в свойстве state компонента. Таким образом, мы будем иметь доступ к сообщениям через this.state.messages и сможем передавать их во все дочерние элементы чата.
Для начала работы над сообщениями воспользуемся «рыбой», а позже заменим фиктивные сообщения на данные от Chatkit API.
Создадим переменную DUMMY_DATA:
const DUMMY_DATA = [ { senderId: "perborgen", text: "who'll win?" }, { senderId: "janedoe", text: "who'll win?" } ]
Теперь, добавим эти данные в state компонента App и передадим в MessageList как свойство.
class App extends React.Component { constructor() { super() this.state = { messages: DUMMY_DATA } } render() { return ( <div className="app"> <MessageList messages={this.state.messages} /> <SendMessageForm /> </div> ) } }
Так, мы инициализируем state в конструкторе и передаем this.state.messages компоненту MessageList. Обратите внимание, что мы использовали super(). Необходимо делать это каждый раз, когда вам нужен компонент с запоминанием состояния.
Шаг 4: рендеринг сообщений
Посмотрим, как можно отрисовать сообщения в компоненте MessageList:
class MessageList extends React.Component { render() { return ( <ul className="message-list"> {this.props.messages.map(message => { return ( <li key={message.id}> <div> {message.senderId} </div> <div> {message.text} </div> </li> ) })} </ul> ) } }
Это так называемый «глупый» компонент. Он принимает единственное свойство messages, которое содержит массив объектов. Затем, он просто рендерит свойства text и senderId из этих объектов.
В нашем случае, рендер будет выглядеть следующим образом:
Теперь у нас есть каркас приложения, и мы можем рендерить сообщения. Заменим фиктивные сообщения на настоящие.
Шаг 5: получаем API-ключ для Chatkit
Chatkit – это инструмент для быстрого создания пользовательских чатов внутри существующих приложений. Чтобы начать с ним работу, нам нужно получить доступ к API сервиса.
Начнем с регистрации аккаунта.
В работе нам понадобится 4 значения из личного кабинета:
- Instance Locator
- Test Token Provider
- Room id
- Username
Instance Locator:
Чуть ниже находится Test Token Provider:
Следующим шагом нужно создать User и Room, что делается на той же странице. В первую очередь необходимо создать пользователя, потом можно будет создать комнату и получить ее id.
Шаг 6: рендерим настоящий чат на React
Теперь вернемся в index.js и сохраним полученные идентификаторы в виде переменных. Пример выглядит так:
const instanceLocator = "v1:us1:dfaf1e22-2d33-45c9-b4f8-31f634621d24" const testToken = "https://us1.pusherplatform.io/services/chatkit_token_provider/v1/ dfaf1e22-2d33-45c9-b4f8-31f634621d24/token" const username = "perborgen" const roomId = 9796712
С этими данными мы готовы подключиться к Chatkit. Это будет происходить в методе componentDidMount компонента App.
В первую очередь создаем ChatManager:
componentDidMount() { const chatManager = new Chatkit.ChatManager({ instanceLocator: instanceLocator, userId: username, tokenProvider: new Chatkit.TokenProvider({ url: testToken }) })
Затем вызовем chatManager.connect(), чтобы подключиться к API:
chatManager.connect().then(currentUser => { currentUser.subscribeToRoom({ roomId: roomId, hooks: { onNewMessage: message => { this.setState({ messages: [...this.state.messages, message] }) } } }) }) }
Так мы получим доступ к объекту currentUser, который послужит интерфейсом для взаимодействия с API. Поскольку с currentUser нам еще предстоит работать, сохраним его в this.currentUser = currentUser.
Дальше мы вызываем currentUser.subscribeToRoom() и передаем наш roomId в хук onNewMessage. Хук срабатывает каждый раз, когда сообщение передается в комнату, и в этот момент мы просто передаем новое сообщение в конец this.state.messages.
Так будет выглядеть результат наших последних действий после рендера:
Шаг 7: обрабатываем пользовательский ввод
Теперь нам нужно создать компонент SendMessageForm. SendMessageForm будет так называемым «контролируемым» компонентом. Это значит, что данный компонент контролирует рендер в поле ввода через свой state.
Рассмотрим метод render():
class SendMessageForm extends React.Component { render() { return ( <form className="send-message-form"> <input onChange={this.handleChange} value={this.state.message} placeholder="Type your message and hit ENTER" type="text" /> </form> ) } }
Здесь мы делаем две вещи:
- Следим за пользовательским вводом с помощью onChange, благодаря которому можем инициировать метод handleChange.
- Устанавливаем значение value поля ввода используя this.state.message.
Эти два действия соединяются в методе handleChange. Он просто обновляет состояние в соответствии с тем, что ввел пользователь:
handleChange(e) { this.setState({ message: e.target.value }) }
Затем страница перерисовывается, и поскольку поле ввода задано явно из состояния с использованием value={this.state.message}, оно будет обновляться.
Теперь дадим компоненту конструктор. В нем мы инициализируем state и привяжем к this метод handleChange:
constructor() { super() this.state = { message: '' } this.handleChange = this.handleChange.bind(this) }
Привязка handleChange нужна затем, чтобы мы могли получить доступ к this внутри этого метода.
Шаг 8: отправка сообщений
Компонент SendMessageForm почти завершен, осталось только позаботиться об отправке данных. Для этого мы будем вызывать обработчик handleSubmit при onSubmit компонента формы.
render() { return ( <form onSubmit={this.handleSubmit} className="send-message-form"> <input onChange={this.handleChange} value={this.state.message} placeholder="Type your message and hit ENTER" type="text" /> </form> ) }
Чтобы отправить нужные данные, делаем следующее:
handleSubmit(e) { e.preventDefault() this.props.sendMessage(this.state.message) this.setState({ message: '' }) }
Здесь мы вызвали sendMessage и передали ему this.state.message в качестве параметра. Мы еще не создали метод sendMessage, но займемся этим в следующем шаге, так как это метод компонента App.
SendMessageForm целиком выглядит следующим образом:
class SendMessageForm extends React.Component { constructor() { super() this.state = { message: '' } this.handleChange = this.handleChange.bind(this) this.handleSubmit = this.handleSubmit.bind(this) } handleChange(e) { this.setState({ message: e.target.value }) } handleSubmit(e) { e.preventDefault() this.props.sendMessage(this.state.message) this.setState({ message: '' }) } render() { return ( <form onSubmit={this.handleSubmit} className="send-message-form"> <input onChange={this.handleChange} value={this.state.message} placeholder="Type your message and hit ENTER" type="text" /> </form> ) } }
Шаг 9: отправка сообщений в Chatkit
Приложение готово к отправке сообщений в Chatkit. Это будет происходить в компоненте App, в котором мы создадим метод this.sendMessage:
sendMessage(text) { this.currentUser.sendMessage({ text, roomId: roomId }) }
Метод принимает один параметр (текст сообщения). Передадим его в качестве свойства в <SendMessageForm>:
render() { return ( <div className="app"> <Title /> <MessageList messages={this.state.messages} /> <SendMessageForm sendMessage={this.sendMessage} /> ) }
Шаг 10: компонент Title
Завершим чат на React, создав компонент для отображения заголовка. Это простой функциональный компонент:
function Title() { return <p class="title">My awesome chat app</p> }
Вот и все, теперь у вас есть собственный мессенджер! Еще раз напомним: если у вас возникнут трудности с пониманием материала, попробуйте поиграть с кодом на Scrimba, чтобы лучше разобраться в деталях уже работающего приложения.