Ubah status secara dinamis berdasarkan konektivitas Internet eksternal - React (offline / online)


9

Saya memiliki komponen Bereaksi, yang mencakup bendera ketersediaan konektivitas Internet. Elemen UI harus diubah secara dinamis sesuai dengan keadaan waktu-nyata. Juga, fungsi berperilaku berbeda dengan perubahan bendera.

Implementasi saya saat ini polling API jarak jauh menggunakan Axios di setiap detik menggunakan interval dan memperbarui negara sesuai. Saya mencari cara yang lebih terperinci dan efisien untuk melakukan tugas ini untuk menghapus kesalahan negara 1 detik dengan biaya komputasi minimum. Dianggap online jika dan hanya jika perangkat memiliki koneksi Internet eksternal

Implementasi saat ini:

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

Diedit:

Mencari solusi yang mampu mendeteksi konektivitas Internet eksternal. Perangkat dapat terhubung ke LAN yang tidak memiliki koneksi eksternal. Jadi, ini dianggap offline. Mempertimbangkan secara online jika dan hanya jika perangkat memiliki akses ke sumber daya Internet eksternal.


2
apakah Anda perlu tahu apakah Anda sedang offline atau online? atau konektivitas internet apa?
tudor.gergely

Ya. Pada dasarnya online atau offline.
Nilanka Manoj

Bisakah Anda mengubah API sehingga memperlihatkan koneksi websocket?
yadejo

Jawaban:


2

Metode satu: Menggunakan API browser lama - Navigator.onLine

Mengembalikan status online browser. Properti mengembalikan nilai boolean, dengan arti sebenarnya online dan makna palsu offline. Properti mengirim pembaruan setiap kali kemampuan browser untuk terhubung ke jaringan berubah. Pembaruan terjadi ketika pengguna mengikuti tautan atau ketika skrip meminta halaman jarak jauh. Misalnya, properti seharusnya kembali false ketika pengguna mengklik tautan segera setelah mereka kehilangan koneksi internet.

Anda dapat menambahkannya ke siklus hidup komponen Anda:

Mainkan dengan kode di bawah ini menggunakan alat dev Chrome - alihkan "Online" ke "Offline" di bawah tab Network.

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>


Namun, saya pikir ini bukan yang Anda inginkan, Anda menginginkan validator koneksi waktu nyata .

Metode dua: Memeriksa koneksi internet dengan menggunakannya

Satu-satunya konfirmasi yang solid yang bisa Anda dapatkan jika konektivitas internet eksternal berfungsi adalah dengan menggunakannya. Pertanyaannya adalah server mana yang harus Anda hubungi untuk meminimalkan biaya?

Ada banyak solusi di internet untuk ini, semua titik akhir yang merespons dengan status cepat 204 sempurna, misalnya:

  • menelepon ke server Google (untuk itu yang paling teruji-perang (?))
  • memanggil titik akhir skrip JQuery yang telah di-cache (jadi meskipun server sedang down, Anda masih bisa mendapatkan skrip selama Anda memiliki koneksi)
  • coba ambil gambar dari server yang stabil (mis .: https://ssl.gstatic.com/gb/images/v1_76783e20.png + stempel waktu tgl untuk mencegah caching)

IMO, jika Anda menjalankan aplikasi Bereaksi ini di server, masuk akal untuk menelepon ke server Anda sendiri, Anda dapat memanggil permintaan untuk memuat Anda /favicon.icountuk memeriksa koneksi.

Ide ini (memanggil server Anda sendiri) telah diterapkan oleh banyak perpustakaan, seperti Offline, is-reachable, dan secara luas digunakan di seluruh masyarakat. Anda dapat menggunakannya jika Anda tidak ingin menulis semuanya sendiri. (Secara pribadi saya suka paket NPM is-reachablekarena sederhana.)

Contoh:

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

Edit Pengujian Koneksi Server

Saya percaya apa yang Anda miliki saat ini sudah baik-baik saja, pastikan saja itu memanggil titik akhir yang tepat.


Pertanyaan SO serupa:


8

Anda dapat menggunakan https://developer.mozilla.org/en-US/docs/Web/API/Window/offline_event

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

dan https://developer.mozilla.org/en-US/docs/Web/API/Window/online_event untuk memeriksa ketika Anda kembali online

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

LAN dapat diputus secara eksternal dalam situasi saya :(
Nilanka Manoj

2

Siapkan pengait khusus

Siapkan pengait dengan aktivitas online dan offline. kemudian perbarui status dan kembalikan. Dengan cara ini Anda dapat menggunakannya di mana saja di aplikasi Anda dengan impor. Pastikan Anda membersihkan dengan fungsi pengembalian. Jika tidak, Anda akan menambah lebih banyak pendengar acara setiap kali komponen menggunakan kait pemasangan.

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
}

Untuk menggunakan ini, cukup impor kait di atas dan sebut seperti ini.

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

LAN dapat diputus secara eksternal dalam situasi saya :(
Nilanka Manoj

3
Jika Anda menggunakan layanan socketed seperti firebase, Anda dapat menggunakan acara bawaan yang menangkap konektivitas internet.
Joe Lloyd

dapatkah Anda memberikan kerangka dasar kode untuk pendekatan yang disarankan.
Nilanka Manoj

2

Anda dapat membuat komponen untuk dibagikan di antara semua subkomponen

bekas:

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

}

Anda lupa menghapus pendengar acara?
gautamits
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.