Combiner React Avec Socket.io Pour Des Applications En Temps Réel

Les concepts de base dans cet article devraient se traduire facilement en d’autres frameworks comme Vue et Angular. Cela dit, pour le reste de la publication, je suppose que vous utilisez React ou React-Native.

Vous devez donc faire en sorte que votre application réagit aux événements du serveur, et en  temps réel, ce qui signifie que vous n’allez pas compter uniquement sur le client pour décider quand obtenir les données du serveur, mais le serveur transmet les données au client dès qu’elles sont disponibles. Les données sont transmises au client à partir du serveur, au lieu d’être extraites du client.

Ce type de modèle est parfaitement adapté à une variété d’applications, par exemple, le chat, les jeux, le trading, etc. Cela dit, de plus en plus d’équipes l’adoptent pour des cas d’utilisation où le produit n’est pas requis, mais plutôt rendre le produit plus réactif.

Quelles que soient vos raisons, je pense qu’il est prudent de supposer que vous lisez ce post parce que vous êtes intéressé à voir comment combiner les sockets et React pour rendre votre application plus en temps réel.

Cet article utilise un exemple super simple, où nous publions l’heure actuelle à partir du socket serveur, juste abonnez-vous sur le client pour afficher la valeur au fur et à mesure de sa mise à jour.

Configuration des bases

Pour commencer, je vais supposer que vous avez déjà les bases installées comme node et npm.

Si vous ne l’avez pas déjà, vous devrez installer create-react-app pour commencer. Cela peut être facilement fait en exécutant la commande suivante pour l’installer globalement: npm –global i create-react-app

Vous pouvez maintenant générer l’application que nous utiliserons pour jouer avec les sockets en exécutant la commande suivante: create-react-app socket-timer

Une fois l’application générée, ouvrez le dossier avec votre éditeur de texte favori. Pour exécuter le projet, tout ce que vous avez à faire est d’exécuter npm start dans le dossier de l’application.

Nous allons exécuter le serveur et le client dans la même base de code, ce que vous ne feriez probablement pas dans une application de production, mais cela facilitera le suivi.

Socket.io sur le serveur

Créons un service WebSocket rapidement. Pour ce faire, placez-vous dans un terminal du dossier de votre application et installez le fichier socket.io: npm i –save socket.io

Maintenant que socket.io est installé, créez un fichier appelé server.js dans le dossier racine de l’application que vous avez générée précédemment. Et à l’intérieur de ce fichier, vous pouvez taper le code suivant pour importer et construire le socket.

const io = require('socket.io')();

Ok, donc on l’importe et on le construit. Nous allons utiliser la variable io pour faire notre magie de socket. Les Websockets sont de longs canaux duplex entre le client et le serveur. Ainsi, la chose la plus importante à faire sur le serveur est de gérer une connexion d’un client, de sorte que vous puissiez publier (émettre) des événements sur ce client. Alors faisons ça:

io.on('connection', (client) => {
  // here you can start emitting events to the client 
});

Une fois que vous avez fait cela, vous devez également indiquer à socket.io de commencer à écouter les clients.

const port = 8000;
io.listen(port);
console.log('listening on port ', port);

Génial! Alors maintenant, vous pouvez aller dans votre terminal et démarrer le serveur en exécutant node server. Vous devriez voir un message qu’il a démarré avec succès: listening on port 8000.

À l’heure actuelle, le service de socket ne fait rien. Vous avez accès aux sockets client, mais vous ne leur envoyez rien pour le moment. Étant donné que vous avez accès à un client connecté dans ce cadre, vous pouvez répondre aux événements émis par le client. Pensez-y comme un gestionnaire d’événements côté serveur se rapportant à un événement spécifique d’un client spécifique.

À la fin, nous voulons que le service démarre un intervalle (timer) et renvoie la date actuelle au client. Nous voulons que le service démarre un minuteur par client et que le client puisse passer l’intervalle de temps souhaité. C’est un point important car cela signifie que les clients peuvent envoyer des données à la socket du serveur. Changez votre code pour ajouter ce qui suit:

io.on('connection', (client) => {
  client.on('subscribeToTimer', (interval) => {
    console.log('client is subscribing to timer with interval ', interval);
  });
});

Ok, maintenant vous avez codé la structure de base pour gérer une connexion client et pour gérer ce dit client en émettant un événement pour démarrer une minuterie pour celui ci. Vous pouvez maintenant démarrer le minuteur et commencer à renvoyer des événements au client contenant l’heure actuelle, alors changez votre code pour qu’il ressemble à ceci:

io.on('connection', (client) => {
  client.on('subscribeToTimer', (interval) => {
    console.log('client is subscribing to timer with interval ', interval);
    setInterval(() => {
      client.emit('timer', new Date());
    }, interval);
  });
});

Bien! Alors maintenant vous avez activé un socket et commencé à l’écouter pour les clients. Lorsqu’un client se connecte, vous avez une fermeture où vous pouvez gérer les événements d’un client particulier. Vous gérez également un événement spéciphique,  subscribeToTimer, étant émis par le client où vous démarrez une minuterie. Lorsque votre minuteur se déclenche, vous émettez un événement, timer  (une minuterie), de retour au client.

À ce stade, votre fichier server.js devrait ressembler à ceci:

const io = require('socket.io')();
io.on('connection', (client) => {
  client.on('subscribeToTimer', (interval) => {
    console.log('client is subscribing to timer with interval ', interval);
    setInterval(() => {
      client.emit('timer', new Date());
    }, interval);
  });
});
const port = 8000;
io.listen(port);
console.log('listening on port ', port);

C’est tout pour le côté serveur de notre installation de socket.io! Passons au client. Assurez-vous simplement que votre dernier code de serveur s’exécute en exécutant node server dans un terminal. Si vous avez démarré ceci avant de faire vos dernières modifications, il suffit de le redémarrer.

Socket.io sur le client

Vous avez démarré l’application React plus tôt en exécutant npm start sur la ligne de commande. Vous devriez donc pouvoir entrer dans votre code, apporter des modifications et actualiser votre navigateur pour voir le recharger votre application avec les modifications.

La première chose que vous voulez faire maintenant est de lier le code de socket client qui communiquera avec le socket côté serveur pour démarrer un timer, en lancant subscribeToTimer, et consommer les événements de timer émis par le serveur.

Pour ce faire, créez un fichier dans le dossier src appelé api.js. Dans le fichier api.js, vous voulez créer une fonction qui peut être appelée pour émettre l’événement subscribeToTimer sur le serveur et renvoyer les résultats de l’événement timer au code consommateur.

Vous pouvez commencer par définir la fonction et l’exporter à partir du module:

function subscribeToTimer(interval, cb) {
} 
export { subscribeToTimer }

Nous préférons donc utiliser une fonction node style, où l’appelant de cette fonction peut passer dans un intervalle pour le timer sur le premier paramètre, et une fonction de rappel sur le deuxième paramètre.

Puisque nous voulons communiquer avec le socket sur le serveur, nous devons installer la bibliothèque  socket.io client. Sur la ligne de commande, installez-la en utilisant npm:

npm i –save socket.io-client

Et maintenant que vous l’avez installé, vous pouvez aller de l’avant et l’importer. Ici, nous pouvons utiliser la syntaxe du module ES6 parce que nous exécutons le côté client du code qui sera transpiré avec Webpack et Babel. Vous pouvez également construire le socket en appelant la fonction d’exportation principale à partir du module socket.io-client, en fournissant un port, qui dans notre cas est 8000.

import openSocket from 'socket.io-client';
const socket = openSocket('http://localhost:8000');

Sur le serveur, nous attendons qu’un client émette l’événement subscribeToTimer sur le serveur avant de démarrer une minuterie, puis lance l’événement timer au client chaque fois que le minuteur se déclenche.

Ce que nous devons faire maintenant, c’est nous abonner d’abord à l’événement du timer provenant du serveur, puis lancer l’événement subscribeToTimer. Chaque fois que nous recevons un événement de timer du serveur, nous appelons la fonction de rappel avec le résultat:

import openSocket from 'socket.io-client';
const  socket = openSocket('http://localhost:8000');
function subscribeToTimer(cb) {
  socket.on('timer', timestamp => cb(null, timestamp));
  socket.emit('subscribeToTimer', 1000);
}
export { subscribeToTimer };

Notez que nous nous sommes abonnés à l’événement timer sur le socket avant de lancer l’événement subscribeToTimer. Nous l’avons fait dans le cas où nous rencontrions une condition de concurrence dans laquelle les événement timer sont émis depuis le serveur, mais le client ne s’y est pas encore intéressé, entraînant la disparition d’événements.

Comment Utiliser Les Evénements Dans Un Composant React

Maintenant, vous devriez avoir un fichier appelé api.js du côté client qui exporte une fonction que vous pouvez appeler pour vous abonner aux événements du timer. Ensuite, vous verrez comment vous pouvez utiliser cette fonction dans votre composant React pour afficher la valeur du timer chaque fois que le serveur l’émet.

En haut du fichier App.js qui a été généré par create-react-app, importez l’API que nous avons créée précédemment.

import { subscribeToTimer } from './api';

Maintenant que vous avez fait cela, vous pouvez aller de l’avant et ajouter un constructeur pour le composant et à l’intérieur de ce constructeur, appelez la fonction subscribetoTimer que vous obtenez du fichier api. Chaque fois que vous obtenez un événement, définissez simplement une valeur appelée timestamp on state en utilisant la valeur provenant du serveur.

constructor(props) {
  super(props);
  subscribeToTimer((err, timestamp) => this.setState({ 
    timestamp 
  }));
}

Parce que vous allez utiliser la valeur d’horodatage sur l’état, il est logique d’ajouter une valeur par défaut pour cela. Ajoutez ce bit de code juste en dessous de votre constructeur pour définir un état par défaut:

state = {
  timestamp: 'no timestamp yet'
};

Et maintenant vous pouvez mettre à jour votre fonction render pour rendre (l’horodatage) timestamp que vous avez défini sur l’état dans le gestionnaire d’événements.

render() {
  return (
    <div className="App">
      <p className="App-intro">
      This is the timer value: {this.state.timestamp}
      </p>
    </div>
  );
}

Et c’est tout! Dans le navigateur, vous devriez être en mesure de voir les événements provenant du serveur et rendus dans votre composant React.

Source: Article traduit depuis sa version originale en anglais  de son auteur Hendrik Swanepoel, Ingénieur en JS.

Note de l’auteur: L’auteur original de cet article a précisé qu’il a souvent utilisé ce modèle dans son code, et que cela fonctionne bien, et que vous pouvez l’appliquer pour gérer plus de complexité, sans rencontrer de problèmes. Cela dit, il y a un peu plus à développer des applications en temps réel avec React et Socket.io. il a promis qu’il va partager un tas d’articles avec vous sur ce sujet, même certains sur l’utilisation de RethinkDb pour gérer la mise à l’échelle de vos sockets. de ma part je ferais en sorte de vous trasmettre tout ses articles traduis fidèlement.

LAISSER UN COMMENTAIRE

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.