Artigo original: Learn to build a React chat app in 10 minutes - React JS tutorial

1_NE_xQlf9WZkO3LTpxG5TNA
Clique aqui para acessar o curso completo (em inglês) no qual este artigo é baseado.

Neste artigo, mostrarei a maneira mais fácil possível de se criar uma aplicação de bate-papo usando o React.js. Isso será feito totalmente sem código do lado do servidor, pois deixaremos a API do Chatkit cuidar do back-end.

Presumo que você saiba o básico de JavaScript e que já tenha visto um pouco de React.js antes. Fora isso, não há pré-requisitos.

Observação: também criei um curso completo e gratuito sobre como criar uma aplicação de bate-papo React.js aqui.

Se seguir este tutorial, você terá sua própria aplicação de bate-papo no final, que poderá ser melhorada posteriormente, se desejar.

Vamos começar!

Etapa 1: divisão da interface do usuário (UI) em componentes

O React foi desenvolvido com base em componentes. Portanto, a primeira coisa que você deve fazer ao criar uma aplicação é dividir a interface do usuário em componentes.

Vamos começar desenhando um retângulo ao redor de toda a aplicação. Esse é o componente raiz e o ancestral comum de todos os outros componentes. Vamos chamá-lo de App:

1_66jz6LtljJtOPDouK9PmYA

Depois de definir o componente raiz, você precisa se fazer a seguinte pergunta:

Quais filhos diretos esse componente tem?

No nosso caso, faz sentido dar a ele três componentes filhos, que chamaremos de:

  • Title (Título)
  • MessagesList (Lista de mensagens)
  • SendMessageForm (Formulário de envio de mensagens)

Vamos desenhar um retângulo para cada um deles:

1_SUeSr13iO7yJfIf4ipaeFg--1-

Isso nos dá uma boa visão geral dos diferentes componentes e da arquitetura por trás da nossa aplicação.

Poderíamos ter continuado e nos perguntado quais são os filhos desses componentes. Assim, poderíamos ter dividido a interface do usuário em ainda mais componentes, por exemplo, transformando cada uma das mensagens em seus próprios componentes. No entanto, vamos parar por aqui por uma questão de simplicidade.

Etapa 2: configuração da base de código

Agora, precisamos configurar nosso repositório. Usaremos a estrutura mais simples possível: um arquivo *index.html * com links para um arquivo JavaScript e uma stylesheet. Também estamos importando o Chatkit SDK e o Babel, que é usado para transformar nosso JSX:

1_YCcPOlQGBk-dP-UQnyLEMA

Aqui está um playground do Scrimba com o código final do tutorial. Recomendo que você o abra em uma nova guia e brinque com ele sempre que se sentir confuso.

1_xmr7Z2oR1PwJvLq2sHuZbQ

Como alternativa, você pode fazer o download do projeto do Scrimba como um arquivo .zip e executar um servidor simples para colocá-lo em funcionamento localmente.

Etapa 3: criação do componente raiz

Com o repositório instalado, podemos começar a escrever algum código em React, o que faremos dentro do arquivo *index.js *.

Vamos começar pelo componente principal, App. Esse será nosso único componente "inteligente", pois tratará dos dados e da conexão com a API. Esta é a configuração básica para ele (antes de adicionarmos qualquer lógica):

    class App extends React.Component {
      
      render() {
        return (
          <div className="app">
            <Title />
            <MessageList />
            <SendMessageForm />
         </div>
        )
      }
    }

Como você pode ver, ele simplesmente renderiza três filhos: os componentes <Title>,<MessageList>, e <SendMessageForm>.

No entanto, vamos torná-lo um pouco mais complexo, pois as mensagens de bate-papo precisarão ser armazenadas dentro do estado (em inglês, state) desse componente App. Isso nos permitirá acessar as mensagens por meio de this.state.messages e, assim, passá-las para outros componentes.

Começaremos com o uso de dados fictícios para que possamos entender o fluxo de dados da aplicação. Em seguida, trocaremos esses dados por dados reais da API do Chatkit.

Vamos criar uma variável DUMMY_DATA:

    const DUMMY_DATA = [
      {
        senderId: "perborgen",
        text: "who'll win?"
      },
      {
        senderId: "janedoe",
        text: "who'll win?"
      }
    ]

Em seguida, adicionaremos esses dados ao estado da aplicação e os passaremos para o componente MessageList como uma propriedade.

    class App extends React.Component {
      
      constructor() {
        super()
        this.state = {
           messages: DUMMY_DATA
        }
      }
      
      render() {
        return (
          <div className="app">
            <MessageList messages={this.state.messages}/>
            <SendMessageForm />
         </div>
        )
      }
    }

Aqui, estamos inicializando o estado no constructor e também estamos passando this.state.messages para MessageList.

Observe que estamos chamando super() no construtor. Você deve fazer isso se quiser criar um componente com estado (em inglês, stateful).

Etapa 4: renderização de mensagens fictícias

Vamos ver como podemos renderizar essas mensagens no componente MessageList. Veja como fica:

    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>
        )
      }
    }

Esse é o chamado componente estúpido. Ele usa uma propriedade, messages, que contém um array de objetos. Então, estamos simplesmente renderizando as propriedades text e senderId dos objetos.

Com nossos dados fictícios fluindo para esse componente, ele renderizará o seguinte:

1_Nf12vqc4Ti_GWY0FwqmQKw

Portanto, agora temos a estrutura básica da nossa aplicação e também podemos renderizar mensagens. Excelente trabalho!

Agora, vamos substituir nossos dados fictícios por mensagens reais de uma sala de bate-papo!

Etapa 5: obtenção de chaves de API do Chatkit

Para buscar mensagens, precisaremos nos conectar à API do Chatkit. Para isso, precisamos obter as chaves da API.

Neste ponto, quero incentivá-lo a seguir minhas etapas para que você possa colocar sua própria aplicação de bate-papo em funcionamento. Você pode usar meu playground do Scrimba para testar suas próprias chaves de API.

Comece criando uma conta gratuita aqui. Depois de fazer isso, você verá seu painel de controle. É aqui que você cria instâncias do Chatkit. Crie uma e dê a ela o nome que você quiser:

image-72

Em seguida, você será direcionado para a instância recém-criada. Aqui, você precisará copiar quatro valores:

  • O localizador de instâncias (instance locator)
  • O provedor do token de teste (test token provider)
  • O ID da sala (room ID)
  • O nome de usuário

Começaremos com o localizador de instâncias:

1_AkbH5NfvHfwHAxiun37k9g

Você pode copiar usando o ícone no lado direito do localizador de instâncias.

Se você rolar a tela um pouco para baixo, encontrará o provedor do token de teste:

1_uSvabQgYrppTGsWKXQsJSQ

O próximo passo é criar um Usuário e uma Sala, o que é feito na mesma página. Observe que, primeiro, será necessário criar um usuário e, em seguida, você poderá criar uma sala, o que dará a você acesso ao identificador da sala.

1_hCXjDJ3PQJ_emU4WfJRQEQ
No segundo círculo vermelho, você vê o identificador da sala

Agora, você encontrou os seus quatro identificadores. Muito bem!

No entanto, antes de voltarmos à base de código, quero que você também envie manualmente uma mensagem do painel do Chatkit, pois isso nos ajudará no próximo capítulo.

Veja como fazer isso:

1_HU3mzUknYj8_MwY7ceK2Ow

Isso é para que tenhamos de fato uma mensagem para renderizar na próxima etapa.

Etapa 6: renderização de mensagens reais de bate-papo

Agora, vamos voltar ao nosso arquivo index.js e armazenar esses quatro identificadores como variáveis na parte superior do nosso arquivo.

Aqui estão as minhas, mas eu o encorajo a criar as suas próprias:

    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

Com isso pronto, finalmente estamos prontos para nos conectar ao Chatkit. Isso ocorrerá no componente App e, mais especificamente, no método componentDidMount. Esse é o método que você deve usar ao conectar componentes React.js a APIs.

Primeiro, criaremos um chatManager:

    componentDidMount() {
      const chatManager = new Chatkit.ChatManager({
        instanceLocator: instanceLocator,
        userId: userId,
        tokenProvider: new Chatkit.TokenProvider({
          url: testToken
        })
     })  

Em seguida, usaremos chatManager.connect() para nos conectarmos à API:

      chatManager.connect().then(currentUser => {
          currentUser.subscribeToRoom({
          roomId: roomId,
          hooks: {
            onNewMessage: message => {
              this.setState({
                messages: [...this.state.messages, message]
              })
            }
          }
        })
      })
    }

Isso nos dá acesso ao objeto currentUser, que é a interface para interagir com a API.

Observação: como precisaremos usar o currentUser mais tarde, vamos armazená-lo na instância, com this.currentUser = ``currentUser.

Em seguida, chamamos currentUser.subscribeToRoom() e passamos a ele nosso roomId e um hook onNewMessage.

O hook onNewMessage é acionado toda vez que uma nova mensagem é transmitida para a sala de bate-papo. Portanto, toda vez que isso acontecer, simplesmente adicionaremos a nova mensagem no final de this.state.messages.

Isso faz com que a aplicação busque dados da API e depois os renderize na página.

1_EAi9TyUba39xN3fciic3aA

Isso é fantástico, pois agora temos o esqueleto da nossa conexão client-servidor.

Uau!

Etapa 7: manipulação de entrada do usuário

A próxima coisa que precisaremos criar é o componente SendMessageForm. Esse será o chamado componente controlado, o que significa que o componente controla o que está sendo renderizado no campo de entrada por meio de seu estado.

Dê uma olhada no método 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>
        )
      }
    }

Estamos fazendo duas coisas:

  1. Ouvir as entradas do usuário com o ouvinte de eventos onChange, de modo que possamos acionar o método handleChange
  2. Definir o value do campo de entrada explicitamente usando this.state.message

A conexão entre essas duas etapas é encontrada dentro do método handleChange. Ele simplesmente atualiza o estado para o que quer que o usuário digite no campo de entrada:

    handleChange(e) {
      this.setState({
        message: e.target.value
      })
    }

Isso aciona uma nova renderização e, como o campo de entrada é definido explicitamente a partir do estado usando value={this.state.message},  o campo de entrada será atualizado.

Portanto, mesmo que a aplicação pareça instantânea para o usuário quando ele digita algo no campo de entrada, os dados realmente passam pelo estado antes que o React atualize a interface do usuário.

Para encerrar esse recurso, precisamos dar ao componente um constructor. Nele, inicializaremos o estado e vincularemos this no método handleChange:

    constructor() {
        super()
        this.state = {
           message: ''
        }
        this.handleChange = this.handleChange.bind(this)
    }

Precisamos vincular o método handleChange para que tenhamos acesso à palavra-chave this dentro dele. É assim que o JavaScript funciona: a palavra-chave this é, por padrão, indefinida dentro do corpo de uma função.

Etapa 8: envio de mensagens

Nosso componente SendMessageForm está quase pronto, mas também precisamos cuidar do envio do formulário. Precisamos buscar as mensagens e enviá-las!

Para fazer isso, conectaremos um manipulador uniforme handleSubmit ao ouvinte de eventos onSubmit no <form>.

    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>
        )
      }

Como temos o valor do campo de entrada armazenado em this.state.message, é muito fácil passar os dados corretos junto com o envio. Basta fazer isso:

    handleSubmit(e) {
      e.preventDefault()
      this.props.sendMessage(this.state.message)
      this.setState({
        message: ''
      })
    }

Aqui, estamos chamando a propriedade sendMessage e passando this.state.message como parâmetro. Talvez você esteja um pouco confuso com isso, pois ainda não criamos o método sendMessage. No entanto, faremos isso na próxima seção, pois esse método está dentro do componente App. Portanto, não se preocupe!

Em segundo lugar, estamos limpando o campo de entrada definindo this.state.message como uma string vazia.

Aqui está o componente SendMessageForm completo. Observe que também vinculamos o this ao método handleSubmit:

    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>
        )
      }
    }

Etapa 9: envio de mensagens para o Chatkit

Agora, estamos prontos para enviar as mensagens para o Chatkit. Isso é feito no componente App, onde criaremos um método chamado this.sendMessage:

    sendMessage(text) {
      this.currentUser.sendMessage({
        text: text,
        roomId: roomId
      })
    }

Ele recebe um parâmetro (o texto) e simplesmente chama this.currentUser.sendMessage().

A etapa final é passar isso para o componente <SendMessageForm> como uma propriedade:

    /* App component */
      
    render() {
      return (
        <div className="app">
          <Title />
          <MessageList messages={this.state.messages} />
          <SendMessageForm sendMessage={this.sendMessage} />
      )
    }

Com isso, passamos o manipulador para que SendMessageForm possa invocá-lo quando o formulário for enviado.

Etapa 10: criando o componente Title

Para finalizar, vamos criar também o componente Title. Ele é apenas um componente funcional simples, ou seja, uma função que retorna uma expressão JSX.

    function Title() {
      return <p class="title">My awesome chat app</p>
    }

É uma boa prática usar componentes funcionais, pois eles têm mais restrições do que os componentes de classe, o que os torna menos propensos a bugs.

O resultado

Com isso, você tem sua própria aplicação de bate-papo, que pode ser usada para conversar com seus amigos!

1_KQzdlJJLMGyq5IdZu6cZ1Q

Dê a si mesmo um tapinha nas costas se tiver programado toda a aplicação até o fim.

Se você quiser saber como desenvolver esse exemplo, então confira meu curso gratuito sobre como criar uma aplicação de bate-papo com o React aqui.

Obrigado pela leitura e boa programação! 😀