Status dynamisch basierend auf der externen Internetverbindung ändern - Reagieren (offline / online)

9

Ich habe eine React-Komponente, die das Verfügbarkeitsflag der Internetverbindung enthält. UI-Elemente müssen dynamisch entsprechend dem Status in Echtzeit geändert werden. Außerdem verhalten sich Funktionen beim Flaggenwechsel anders.

Meine aktuelle Implementierung fragt die Remote-API mit Axios in jeder Sekunde anhand des Intervalls ab und aktualisiert den Status entsprechend. Ich suche nach einer detaillierteren und effizienteren Möglichkeit, diese Aufgabe zu erledigen, um den 1-Sekunden-Zustandsfehler bei minimalem Rechenaufwand zu beseitigen. Wird nur dann online betrachtet, wenn das Gerät über eine externe Internetverbindung verfügt

Aktuelle Implementierung:

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} />;
  }
}

Bearbeitet:

Suchen Sie nach einer Lösung, mit der externe Internetverbindungen erkannt werden können. Das Gerät kann eine Verbindung zu einem LAN herstellen, das keine externe Verbindung hat. Es wird also als offline betrachtet. Betrachtet Online genau dann , wenn das Gerät Zugriff auf externe Internetressourcen hat.

Nilanka Manoj
quelle
2
Müssen Sie wissen, ob Sie offline oder online sind? oder welche Internetverbindung?
tudor.gergely
Ja. Grundsätzlich online oder offline.
Nilanka Manoj
Können Sie die API so ändern, dass eine Websocket-Verbindung verfügbar wird?
Yadejo

Antworten:

2

Methode eins: Verwenden der Legacy-Browser-API - Navigator.onLine

Gibt den Online-Status des Browsers zurück. Die Eigenschaft gibt einen booleschen Wert zurück, wobei true online und false offline bedeutet. Die Eigenschaft sendet Aktualisierungen, wenn sich die Fähigkeit des Browsers, eine Verbindung zum Netzwerk herzustellen, ändert. Die Aktualisierung erfolgt, wenn der Benutzer Links folgt oder wenn ein Skript eine Remote-Seite anfordert. Beispielsweise sollte die Eigenschaft false zurückgeben, wenn Benutzer kurz nach dem Verlust der Internetverbindung auf Links klicken.

Sie können es Ihrem Komponentenlebenszyklus hinzufügen:

Spielen Sie mit dem folgenden Code mit den Chrome-Entwicklungstools - wechseln Sie auf der Registerkarte "Netzwerk" zu "Online" zu "Offline".

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>


Ich denke jedoch, dass dies nicht das ist, was Sie wollen, Sie wollten einen Echtzeit- Verbindungsprüfer.

Methode zwei: Überprüfen der Internetverbindung mithilfe dieser

Die einzige solide Bestätigung, die Sie erhalten können, wenn die externe Internetverbindung funktioniert, ist die Verwendung. Die Frage ist, welchen Server Sie anrufen sollten, um die Kosten zu minimieren.

Dafür gibt es im Internet viele Lösungen. Jeder Endpunkt, der mit einem schnellen 204-Status antwortet, ist perfekt, z.

  • Aufrufen des Google-Servers (da dieser am kampferprobtesten ist (?))
  • Aufrufen des zwischengespeicherten JQuery-Skriptendpunkts (selbst wenn der Server nicht verfügbar ist, sollten Sie das Skript dennoch abrufen können, solange Sie eine Verbindung haben).
  • Versuchen Sie, ein Bild von einem stabilen Server abzurufen (z. B. https://ssl.gstatic.com/gb/images/v1_76783e20.png + Datumszeitstempel, um das Zwischenspeichern zu verhindern).

IMO, wenn Sie diese React-App auf einem Server ausführen, ist es am sinnvollsten, auf Ihrem eigenen Server anzurufen. Sie können eine Anforderung zum Laden Ihrer Server aufrufen /favicon.ico, um die Verbindung zu überprüfen.

Diese Idee (von Ihrem eigenen Server aufruft) wird von vielen Bibliotheken, wie implementiert Offline, is-reachableund ist weit verbreitet in der Gemeinschaft verwendet. Sie können sie verwenden, wenn Sie nicht alles selbst schreiben möchten. (Ich persönlich mag das NPM-Paket, is-reachableweil es einfach ist.)

Beispiel:

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

Bearbeiten der Testserververbindung

Ich glaube, was Sie derzeit haben, ist bereits in Ordnung. Stellen Sie nur sicher, dass der richtige Endpunkt aufgerufen wird.


Ähnliche SO-Fragen:

Jee Mok
quelle
8

Sie können https://developer.mozilla.org/en-US/docs/Web/API/Window/offline_event verwenden

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

und https://developer.mozilla.org/en-US/docs/Web/API/Window/online_event, um zu überprüfen, wann Sie wieder online sind

window.addEventListener('online', (event) => {
    console.log("You are now connected to the network.");
});
tudor.gergely
quelle
LAN kann in meiner Situation extern getrennt werden :(
Nilanka Manoj
2

Richten Sie einen benutzerdefinierten Hook ein

Richten Sie einen Hook mit den Online- und Offline-Ereignissen ein. Aktualisieren Sie dann einen Status und geben Sie ihn zurück. Auf diese Weise können Sie es mit einem Import überall in Ihrer App verwenden. Stellen Sie sicher, dass Sie mit der Rückgabefunktion aufräumen. Wenn Sie dies nicht tun, werden Sie jedes Mal mehr Ereignis-Listener hinzufügen, wenn eine Komponente die Hook-Mounts verwendet.

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
}

Um dies zu verwenden, importieren Sie einfach den obigen Hook und nennen Sie ihn so.

const isOnline = onlineHook(); // true if online, false if not
Joe Lloyd
quelle
LAN kann in meiner Situation extern getrennt werden :(
Nilanka Manoj
3
Wenn Sie einen Socket-Dienst wie Firebase verwenden, können Sie ein integriertes Ereignis verwenden, das die Internetverbindung erfasst.
Joe Lloyd
Können Sie ein grundlegendes Code-Skelett für den vorgeschlagenen Ansatz bereitstellen?
Nilanka Manoj
2

Sie können eine Komponente erstellen, die von allen Unterkomponenten gemeinsam genutzt werden soll

benutzt:

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
quelle
Sie haben vergessen, den Ereignis-Listener zu entfernen?
Gautamits