Cambia stato in modo dinamico in base alla connettività Internet esterna - React (offline / online)


9

Ho un componente React, che include il flag di disponibilità della connettività Internet. Gli elementi dell'interfaccia utente devono essere modificati in modo dinamico in base allo stato in tempo reale. Inoltre, le funzioni si comportano diversamente con il cambio di bandiera.

La mia attuale implementazione esegue il polling dell'API remota utilizzando Axios ogni secondo usando l'intervallo e lo stato degli aggiornamenti di conseguenza. Sto cercando un modo più granulare ed efficiente per fare questo compito per rimuovere l'errore di stato di 1 secondo con il costo computazionale minimo. Considerato online se e solo se il dispositivo ha una connessione Internet esterna

Attuazione attuale:

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

Modificato:

Alla ricerca di una soluzione in grado di rilevare la connettività Internet esterna. Il dispositivo può connettersi a una LAN che non ha una connessione esterna. Quindi, è considerato offline. Considera online se e solo se il dispositivo ha accesso a risorse Internet esterne.


2
devi sapere se sei offline o online? o quale connettività internet?
tudor.gergely

Si. Fondamentalmente online o offline.
Nilanka Manoj

potresti modificare l'API in modo che esponga una connessione websocket?
yadejo,

Risposte:


2

Metodo 1: utilizzo dell'API del browser legacy - Navigator.onLine

Restituisce lo stato online del browser. La proprietà restituisce un valore booleano, con significato vero online e significato falso offline. La proprietà invia aggiornamenti ogni volta che cambia la capacità del browser di connettersi alla rete. L'aggiornamento si verifica quando l'utente segue i collegamenti o quando uno script richiede una pagina remota. Ad esempio, la proprietà dovrebbe restituire false quando gli utenti fanno clic sui collegamenti subito dopo aver perso la connessione a Internet.

È possibile aggiungerlo al ciclo di vita del componente:

Gioca con il codice seguente utilizzando gli strumenti di sviluppo di Chrome: passa da "Online" a "Offline" nella scheda Rete.

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>


Tuttavia, penso che questo non sia quello che vuoi, volevi un validatore della connessione in tempo reale .

Metodo due: controllo della connessione a Internet mediante l'utilizzo

L'unica conferma solida che puoi ottenere se la connettività Internet esterna funziona è usarla. La domanda è: quale server dovresti chiamare per minimizzare il costo?

Esistono molte soluzioni su Internet per questo, qualsiasi endpoint che risponde con un rapido stato 204 è perfetto, ad esempio:

  • chiamando al server di Google (perché è il più testato in battaglia (?))
  • chiamando l'endpoint dello script JQuery memorizzato nella cache (quindi, anche se il server è inattivo, dovresti comunque essere in grado di ottenere lo script fintanto che hai una connessione)
  • prova a recuperare un'immagine da un server stabile (ad esempio: https://ssl.gstatic.com/gb/images/v1_76783e20.png + data e ora per evitare la memorizzazione nella cache)

IMO, se stai eseguendo questa app React su un server, ha più senso chiamare il tuo server, puoi chiamare una richiesta per caricare il tuo /favicon.icoper verificare la connessione.

Questa idea (di chiamare il proprio server) è stato implementato da molte biblioteche, come Offline, is-reachableed è ampiamente utilizzato in tutta la comunità. Puoi usarli se non vuoi scrivere tutto da solo. (Personalmente mi piace il pacchetto NPM is-reachableper essere semplice.)

Esempio:

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

Modifica connessione server di prova

Credo che ciò che hai attualmente vada bene, assicurati solo che stia chiamando l'endpoint giusto.


Domande SO simili:


8

Puoi usare https://developer.mozilla.org/en-US/docs/Web/API/Window/offline_event

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

e https://developer.mozilla.org/en-US/docs/Web/API/Window/online_event per controllare quando torni online

window.addEventListener('online', (event) => {
    console.log("You are now connected to the network.");
});

La LAN può essere disconnessa esternamente nella mia situazione :(
Nilanka Manoj

2

Installa un hook personalizzato

Installa un hook con gli eventi online e offline. quindi aggiornare uno stato e restituirlo. In questo modo puoi usarlo ovunque nella tua app con un'importazione. Assicurati di pulire con la funzione di ritorno. In caso contrario, verranno aggiunti sempre più listener di eventi ogni volta che viene montato un componente che utilizza il gancio.

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
}

Per usarlo basta importare l'hook sopra e chiamarlo così.

const isOnline = onlineHook(); // true if online, false if not

La LAN può essere disconnessa esternamente nella mia situazione :(
Nilanka Manoj

3
Se si utilizza un servizio con socket come Firebase, è possibile utilizzare un evento integrato che acquisisce la connettività Internet.
Joe Lloyd,

puoi fornire uno scheletro di base del codice per l'approccio suggerito.
Nilanka Manoj,

2

È possibile creare un componente da condividere tra tutti i sottocomponenti

Usato:

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

}

Hai dimenticato di rimuovere il listener di eventi?
gautamits
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.