Changer l'état dynamiquement en fonction de la connectivité Internet externe - React (hors ligne / en ligne)

9

J'ai un composant React, qui inclut l'indicateur de disponibilité de la connectivité Internet. Les éléments de l'interface utilisateur doivent être modifiés dynamiquement en fonction de l'état en temps réel. De plus, les fonctions se comportent différemment avec le changement de drapeau.

Mon implémentation actuelle interroge l'API distante en utilisant Axios à chaque seconde en utilisant l'intervalle et met à jour l'état en conséquence. Je recherche un moyen plus granulaire et plus efficace de faire cette tâche pour supprimer l'erreur d'état de 1 seconde avec le coût de calcul minimum. Considéré en ligne si et seulement si l' appareil dispose d'une connexion Internet externe

Implémentation actuelle:

class Container extends Component {
  constructor(props) {
    super(props)
    this.state = {
      isOnline: false
    };
    this.webAPI = new WebAPI(); //Axios wrapper
  }

  componentDidMount() {
    setInterval(() => {
      this.webAPI.poll(success => this.setState({ isOnline: success });
    }, 1000);
  }

  render() {
    return <ChildComponent isOnline={this.state.isOnline} />;
  }
}

Édité:

Vous recherchez une solution capable de détecter la connectivité Internet externe. L'appareil peut se connecter à un LAN qui n'a pas de connexion externe. Donc, il est considéré comme hors ligne. Considère en ligne si et seulement si l' appareil a accès à des ressources Internet externes.

Nilanka Manoj
la source
2
avez-vous besoin de savoir si vous êtes hors ligne ou en ligne? ou quelle connectivité internet?
tudor.gergely
Ouais. Fondamentalement en ligne ou hors ligne.
Nilanka Manoj
pourriez-vous modifier l'API afin qu'elle expose une connexion Websocket?
yadejo

Réponses:

2

Méthode 1: Utilisation de l'API de navigateur héritée - Navigator.onLine

Renvoie l'état en ligne du navigateur. La propriété renvoie une valeur booléenne, avec une vraie signification en ligne et une fausse signification hors ligne. La propriété envoie des mises à jour chaque fois que la capacité du navigateur à se connecter au réseau change. La mise à jour se produit lorsque l'utilisateur suit des liens ou lorsqu'un script demande une page distante. Par exemple, la propriété doit retourner false lorsque les utilisateurs cliquent sur des liens peu de temps après avoir perdu leur connexion Internet.

Vous pouvez l'ajouter à votre cycle de vie des composants:

Jouez avec le code ci-dessous à l'aide des outils de développement Chrome - passez de "En ligne" à "Hors ligne" sous l'onglet Réseau.

class App extends React.PureComponent {
  state = { online: window.navigator.onLine }
  
  componentDidMount() {
    window.addEventListener('offline', this.handleNetworkChange);
    window.addEventListener('online', this.handleNetworkChange);
  }
  
  componentWillUnmount() {
    window.removeEventListener('offline', this.handleNetworkChange);
    window.removeEventListener('online', this.handleNetworkChange);
  }
  
  handleNetworkChange = () => {
    this.setState({ online: window.navigator.onLine });
  }
  
  render() {
    return (
      <div>
       { this.state.online ? 'you\'re online' : 'you\'re offline' }
      </div>
    );
  }
}

ReactDOM.render(
  <App />
, document.querySelector('#app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>


Cependant, je pense que ce n'est pas ce que vous voulez, vous vouliez un validateur de connexion en temps réel .

Méthode 2: vérification de la connexion Internet en l'utilisant

La seule confirmation solide que vous pouvez obtenir si la connectivité Internet externe fonctionne est en l'utilisant. La question est quel serveur vous devez appeler pour minimiser le coût?

Il existe de nombreuses solutions sur Internet pour cela, tout point final qui répond avec un statut 204 rapide est parfait, par exemple:

  • appel au serveur Google (car c'est le plus testé au combat (?))
  • appeler son point de terminaison de script JQuery mis en cache (donc même si le serveur est en panne, vous devriez toujours pouvoir obtenir le script tant que vous avez une connexion)
  • essayez de récupérer une image à partir d'un serveur stable (par exemple: https://ssl.gstatic.com/gb/images/v1_76783e20.png + horodatage de la date pour empêcher la mise en cache)

IMO, si vous exécutez cette application React sur un serveur, il est plus judicieux d'appeler sur votre propre serveur, vous pouvez appeler une demande de chargement /favicon.icopour vérifier la connexion.

Cette idée (d'appeler votre propre serveur) a été mis en œuvre par de nombreuses bibliothèques, telles que Offline, is-reachableet est largement utilisé dans la communauté. Vous pouvez les utiliser si vous ne voulez pas tout écrire par vous-même. (Personnellement, j'aime le package NPM is-reachablepour être simple.)

Exemple:

import React from 'react';
import isReachable from 'is-reachable';

const URL = 'google.com:443';
const EVERY_SECOND = 1000;

export default class App extends React.PureComponent {
  _isMounted = true;

  state = { online: false }

  componentDidMount() {
    setInterval(async () => {
      const online = await isReachable(URL);

      if (this._isMounted) {
        this.setState({ online });
      }
    }, EVERY_SECOND);
  }

  componentWillUnmount() {
    this._isMounted = false;
  }

  render() {
    return (
      <div>
       { this.state.online ? 'you\'re online' : 'you\'re offline' }
      </div>
    );
  }
}

Modifier la connexion au serveur de test

Je crois que ce que vous avez actuellement est déjà bien, assurez-vous simplement qu'il appelle le bon point de terminaison.


Questions SO similaires:

Jee Mok
la source
8

Vous pouvez utiliser https://developer.mozilla.org/en-US/docs/Web/API/Window/offline_event

window.addEventListener('offline', (event) => {
    console.log("The network connection has been lost.");
});

et https://developer.mozilla.org/en-US/docs/Web/API/Window/online_event pour vérifier quand vous êtes de retour en ligne

window.addEventListener('online', (event) => {
    console.log("You are now connected to the network.");
});
tudor.gergely
la source
Le LAN peut être déconnecté de l'extérieur dans ma situation :(
Nilanka Manoj
2

Configurer un crochet personnalisé

Configurez un crochet avec les événements en ligne et hors ligne. puis mettez à jour un état et renvoyez-le. De cette façon, vous pouvez l'utiliser n'importe où dans votre application avec une importation. Assurez-vous de nettoyer avec la fonction de retour. Si vous ne le faites pas, vous ajouterez de plus en plus d'écouteurs d'événements à chaque fois qu'un composant utilise les crochets.

const onlineHook = () => {
  const {isOnline, setOnline} = React.useState();

  React.useEffect(() => {
    const goOnline = function(event){
      setOnline(true);
    });
    const goOffline = function(event){
      setOnline(false);
    });

    window.addEventListener('offline', goOffline);
    window.addEventListener('online', goOnline);

    return () => {
      window.removeEventListener('offline', goOffline);
      window.removeEventListener('online', goOnline);      
    }
  }, [])

  return isOnline
}

Pour l'utiliser, importez simplement le crochet ci-dessus et appelez-le comme ceci.

const isOnline = onlineHook(); // true if online, false if not
Joe Lloyd
la source
Le LAN peut être déconnecté de l'extérieur dans ma situation :(
Nilanka Manoj
3
Si vous utilisez un service en socket comme Firebase, vous pouvez utiliser un événement intégré qui capture la connectivité Internet.
Joe Lloyd
pouvez-vous fournir un squelette de code de base pour l'approche suggérée.
Nilanka Manoj
2

Vous pouvez créer un composant à partager entre tous les sous-composants

utilisé:

import React, { useState, useEffect } from "react";

export default function NetworkChecker() {

  const [networkStatus, setNetworkStatus] = useState(true)

  useEffect(() => {
    window.addEventListener('offline', (event) => {
      setNetworkStatus(false)
    });

    window.addEventListener('online', (event) => {
      setNetworkStatus(true)
    });

    return function cleanupListener() {
       window.removeEventListener('online',  setNetworkStatus(true))
       window.removeEventListener('offline', setNetworkStatus(false))
     }

  },[])

  if (networkStatus) {
    return <div className={"alert-success"}>Online</div>
  } else {
    return <div className={"alert-danger"}>Offline</div>
  }

}
Eddwin Paz
la source
Vous avez oublié de supprimer l'écouteur d'événements?
gautamits