https://d226lax1qjow5r.cloudfront.net/blog/blogposts/chat-app-with-react-and-nexmo-dr/React_Nexmo.png

Créer une application de chat avec React et Nexmo

Temps de lecture : 5 minutes

L'un des moyens les plus simples de communiquer en ligne est également l'un des plus simples à ajouter à votre site web. React et l'outillage JavaScript côté client de Nexmo. Une application de chat peut fournir un service client, faciliter la collaboration sur un projet ou vous permettre de prendre des nouvelles de vos amis. Et bonne nouvelle : si vous avez suivi notre précédent tutoriel tutoriel complet sur React et Expressvous disposez déjà de la plupart des éléments nécessaires à la création d'une application de chat.

Conditions préalables

Pour faire court, supposons que vous ayez avez suivi le tutoriel tutoriel React et Express.

Comme dans le code d'exemple à pile complète, le code d'exemple code d'exemple de ce tutoriel répondra à cette dernière exigence en utilisant Glitch.

Si vous utilisez l'Application Nexmo que vous avez créée pour votre application full-stack, vous pouvez générer un ou deux ID de conversation et les copier dans un fichier texte pour les utiliser à l'étape suivante. Si vous préférez créer une nouvelle application pour ce projet, vous pouvez créer les conversations à partir de la ligne de commande.

Vonage API Account

To complete this tutorial, you will need a Vonage API account. If you don’t have one already, you can sign up today and start building with free credit. Once you have an account, you can find your API Key and API Secret at the top of the Vonage API Dashboard.

Ajouter des salles de chat à NexmoApp

Pour séparer les fonctionnalités, ajoutez un nouveau composant à votre application React à l'adresse suivante . client/src/Chatroom.js. Pour l'instant, vous pouvez le laisser pratiquement vide :

import React from 'react';
import styles from './Chatroom.css';

class Chatroom extends React.Component {
  constructor(props) {
    super(props);
    this.state = {};
  }
};

export default Chatroom;

Vous pouvez également ajouter son fichier CSS et l'alimenter avec le style que vous souhaitez à tout moment.

Si vous ouvrez NexmoApp.js vous verrez quelques références au composant Conversation composant. Le composant Chatroom sera utilisé de la même manière, vous pouvez donc les remplacer par des références à Chatroom. Elles doivent se trouver dans les importet dans la fonction render et dans la fonction .

A l'intérieur de rendermodifie légèrement la balise Chatroom de manière à ce qu'au lieu de passer invitesvous passiez chats:

  render() {
    return (
      <div className="nexmo">
        <User onUpdate={this.userUpdated}/>
        <Chatroom app={this.state.app} loggedIn={!!this.state.token} chats={this.state.chats} />
      </div>
    );
  }

Les autres propriétés transmises à Chatroom existent déjà dans le cadre de l'authentification de l'utilisateur et de la connexion, mais chats ne fait pas partie de l'état. Pour cette application simple, codez en dur les conversations que vous avez créées ci-dessus dans l'état initial du composant. Vous pouvez leur donner les noms que vous souhaitez pour les différencier pour les utilisateurs finaux :

constructor(props) {
    super(props);
    this.state = {
      chats: [
        {
          id: 'CON-123e456c-5ff0-789c-8a11-e4a56a7b8c90',
          name: 'nice chat'
        },
        {
          id: 'CON-2c34ecec-f567-8e90-bf1d-23e4567e890a',
          name: 'serious business'
        }
      ]
    };
    
    this.login = this.login.bind(this);
    this.getJWT = this.getJWT.bind(this);
    this.userUpdated = this.userUpdated.bind(this);
  }

Comme cette application ne gère pas les conversations ou les invitations, vous pouvez également supprimer le code dans login pour obtenir les conversations. Cette fonction ne sert plus qu'à se connecter et à stocker une référence à l'application Nexmo :

  login() {
    let nexmo = new nexmoClient();
    nexmo.createSession(this.state.token).then(app => {
      this.setState({
        app: app
      });
    });
  }

Un simple salon de discussion

Vous pouvez laisser tout le User sans rien changer au code du composant. Il continuera à faire la même chose, en créant un nouvel utilisateur ou en proposant une liste d'utilisateurs existants. Une fois que l'utilisateur est connecté, il peut continuer à discuter.

Le composant Chatroom contiendra deux états : le choix d'un salon de discussion et le salon de discussion lui-même. Dans les coulisses, un salon de discussion est simplement une conversation Nexmoune partie du code de ce composant ressemblera donc à ce qui se trouve dans le composant Conversation . Pour commencer, vous pouvez créer les fonctions et les conditions nécessaires aux deux états :

import React from 'react';
import styles from './Chatroom.css';

class Chatroom extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      messages: []
    };
    
    this.joinConversation = this.joinConversation.bind(this);
    this.onMessage = this.onMessage.bind(this);
    this.setInput = this.setInput.bind(this);
    this.sendInput = this.sendInput.bind(this);
  }
  
  joinConversation(evt) {}
  
  onMessage(sender, message) {}
  
  setInput(evt) {}
  
  sendInput() {}
  
  render() {
    if (this.state.conversation) {
      
    } else {
     
    }
  }
};

export default Chatroom;

Rejoindre un chat

Étant donné que l'utilisateur dispose d'un ensemble fini d'espaces de discussion prédéfinis, un menu déroulant lui permet d'en sélectionner un facilement. Si vous n'aviez qu'un seul salon de discussion, vous pourriez vous passer complètement de cette interface. Pour produire une liste déroulante pour les deux salons de discussion codés en dur dans NexmoAppboucle sur le tableau pour construire un ensemble de optionpuis ajoutez-les en tant qu'enfants d'un élément select:

  render() {
    if (this.state.conversation) {
    } else {
      let opts = [<option key="0">-</option>];
      this.props.chats.forEach(chat => {
        opts.push(<option key={chat.id} value={chat.id}>{chat.name}</option>);
      });
      
      return (
        <div className="conversation">
          <label>Choose a chat to join: 
            <select onChange={evt => this.joinConversation(evt)}>
              {opts}
            </select>
          </label>
        </div>
      );
    }
  }

Lorsque la valeur de la liste déroulante change, joinConversation est déclenché. Le gestionnaire joinConversation récupère la conversation choisie par son identifiant dans l'application Nexmo et la rejoint. Il stocke également une référence à cette conversation et lui assigne un autre gestionnaire d'événements pour les messages entrants :

  joinConversation(evt) {
    let select = evt.target;
    this.props.app.getConversation(select.value).then(conv => {
      conv.on('text', this.onMessage);
      conv.join();
      this.setState({
        conversation: conv
      });
    });
  }

Le gestionnaire onMessage est déclenché chaque fois qu'un nouvel événement text dans la conversation active. Il reçoit des informations sur le membre de la conversation qui a déclenché l'événement et sur l'objet de l'événement lui-même. Pour un simple chat, vous pouvez ignorer la plupart de ces informations et n'enregistrer que l'ID, le nom d'affichage de l'utilisateur et le texte du message. Ces informations peuvent être concaténées à une liste de messages stockés dans l'état :

onMessage(sender, message) {
    let newMessages = this.state.messages.concat({
      key: message.id,
      sender: sender.display_name,
      text: message.body.text
    });
    this.setState({
      messages: newMessages
    });
  }

Si vous deviez concevoir un chat aussi simple soit-il pour une utilisation en production, vous devriez prévoir de déplacer les messages plus anciens vers un autre objet de stockage après un certain temps. En cas de trafic important, l'utilisation d'un seul tableau pour contenir tous les messages posera inévitablement des problèmes.

Envoi de messages

Une fois que l'utilisateur est connecté et qu'il a rejoint un chat, il souhaite envoyer et recevoir des messages. Cela signifie que vous voulez rendre une interface utilisateur avec, au minimum, une zone de visualisation des messages et un champ de saisie pour le texte. Le JSX pour cela remplit l'autre branche de la conditionnelle principale dans render. Il itère sur votre tableau de messages et affiche tout ce qui a été reçu depuis que l'utilisateur a rejoint le chat. En dessous, il fournit un champ de texte et un bouton qui définissent le texte nouvellement saisi et l'envoient, respectivement :

  render() {
    if (this.state.conversation) {
      let messagePane = [];
      
      if (this.state.messages.length) {
        this.state.messages.forEach(msg => {
          messagePane.push(<p key={msg.key} className="message"><b>{msg.sender}:</b>{msg.text}</p>);
        });
      }
      
      return (
        <div className="conversation">
          <div className="messages">
            {messagePane}
          </div>
          <div className="input">
            <textarea onBlur={evt => this.setInput(evt)} />
            <button onClick={evt => this.sendInput(evt)}>Chat</button>
          </div>
        </div>
      );
    } else {
      ...
    }
  }

Les événements soulevés par l'entrée du message sont traités dans les modules setInput et sendInput. setInput stocke simplement le texte saisi dans l'état du composant :

  setInput(evt) {
    this.setState({
      input: evt.target.value
    });
  }

Le gestionnaire de bouton, sendInputprend le texte stocké dans l'état et le transmet à la conversation à l'aide de la commande sendText. Il efface ensuite le texte dans l'état et dans la zone de texte qui le précède :

 sendInput(evt) {
    this.state.conversation.sendText(this.state.input).then(() => {
      this.setState({
        input: null
      });
    });
    evt.target.previousSibling.value = '';
  }

Bavardez !

Bien qu'elle ne gère pas les erreurs et qu'elle n'accorde aucune attention aux performances, vous disposez maintenant d'une application de chat très basique. En supprimant les caractéristiques d'une application de production, on se rend compte du peu de choses dont on a besoin pour fournir les fonctionnalités de base d'un chat :

  1. Un utilisateur connecté à une application Nexmo

  2. Une conversation à laquelle l'utilisateur peut se joindre

  3. Un gestionnaire d'événements pour les messages reçus

  4. La fonction sendText pour activer le chat

Que vous souhaitiez créer un salon de discussion à l'ancienne, une conversation contextuelle pour aider des clients désorientés, ou quoi que ce soit d'autre, vous pouvez le faire à partir de ces éléments. Vous n'avez pas besoin de gérer de sockets ou de polling. Et avec React, vous n'avez rien à faire pour déclencher les mises à jour du DOM. Vous pouvez maintenant vous concentrer sur l'interface utilisateur et la robustesse de l'application.

Partager:

https://a.storyblok.com/f/270183/250x250/f231d97f1b/garann-means.png
Garann MeansDéveloppeur Éducateur

Je suis développeur JavaScript et éducateur de développeurs chez Vonage. Au fil des ans, j'ai été très intéressé par les modèles, Node.js, les applications Web progressives et les stratégies offline-first, mais ce que j'ai toujours aimé, c'est une API utile et bien documentée. Mon objectif est de faire en sorte que votre expérience de l'utilisation de nos API soit la meilleure possible.