Пишем собственный чат на React за 10 простых шагов

Рассказываем, как создать собственный чат на React.js с помощью Charset SDK: от создания компонентов до работы со сторонним API.

Шаг 1: раскладываем интерфейс на компоненты

Так как Реакт – компонентный фреймворк, первое, что нам нужно сделать, это представить чат на React как набор элементов.

Начнем с создания корневого компонента – своеобразного холдера для всех остальных элементов приложения:

cabinet

Красный прямоугольник вокруг макета – корневой элемент, назовем его App.

Теперь нужно разобраться с вопросом: какие дочерние элементы должен содержать чат на React.js? В нашем случае, есть смысл создать три дочерних элемента, которые мы назовем следующим образом:

  • Title
  • MessageList
  • SendMessageForm

Выделим их на макете:

cabinet

При построении компонентного приложения, необходимо постоянно спрашивать себя: какие еще компоненты может содержать интерфейс? Таким образом, можно создавать более простые составные части для будущих сложных компонентов.

Шаг 2: настраиваем кодовую базу

Для знакомства с фреймворком воспользуемся самым простым путем сборки приложения: просто создадим файл index.html, к которому подключим необходимые библиотеки и код.

cabinet

Кроме самого Реакта, мы импортируем Charset SDK и Babel, который необходим для преобразования JSX.

Откройте готовый проект в новой вкладке и попробуйте поиграть с кодом, если будете испытывать трудности с пониманием туториала.

cabinet

Также по ссылке проект можно скачать в виде архива и развернуть на локальном сервере.

Шаг 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 из этих объектов.

В нашем случае, рендер будет выглядеть следующим образом:

cabinet

Теперь у нас есть каркас приложения, и мы можем рендерить сообщения. Заменим фиктивные сообщения на настоящие.

Шаг 5: получаем API-ключ для Chatkit

Chatkit – это инструмент для быстрого создания пользовательских чатов внутри существующих приложений. Чтобы начать с ним работу, нам нужно получить доступ к API сервиса.

Начнем с регистрации аккаунта.

cabinet

В работе нам понадобится 4 значения из личного кабинета:

  • Instance Locator
  • Test Token Provider
  • Room id
  • Username

Instance Locator:

cabinet

Чуть ниже находится Test Token Provider:

cabinet

Следующим шагом нужно создать User и Room, что делается на той же странице. В первую очередь необходимо создать пользователя, потом можно будет создать комнату и получить ее id.

cabinet

Шаг 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.

Так будет выглядеть результат наших последних действий после рендера:

chat

Шаг 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>
    )
  }
}

Здесь мы делаем две вещи:

  1. Следим за пользовательским вводом с помощью onChange, благодаря которому можем инициировать метод handleChange.
  2. Устанавливаем значение 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>
}

chat

Вот и все, теперь у вас есть собственный мессенджер! Еще раз напомним: если у вас возникнут трудности с пониманием материала, попробуйте поиграть с кодом на Scrimba, чтобы лучше разобраться в деталях уже работающего приложения.

Оригинал

Больше Реакта:

Комментарии

ВАКАНСИИ

Добавить вакансию
Разработчик C++
Москва, по итогам собеседования

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ