外部インターネット接続に基づいて状態を動的に変更-React(オフライン/オンライン)


9

インターネット接続の可用性フラグを含むReactコンポーネントがあります。UI要素は、状態に応じてリアルタイムで動的に変更する必要があります。また、フラグの変更により、関数の動作が異なります。

現在の実装では、間隔を使用して毎秒Axiosを使用してリモートAPIをポーリングし、それに応じて状態を更新しています。このタスクを実行して、最小の計算コストで1秒の状態エラーを削除する、より詳細で効率的な方法を探しています。デバイスに外部インターネット接続がある場合にのみ、オンライン見なされます

現在の実装:

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

編集:

外部インターネット接続を検出できるソリューションを探しています。デバイスは、外部接続のないLANに接続できます。したがって、オフラインと見なされます。デバイスが外部インターネットリソースにアクセスできる場合にのみ、オンライン見なします。


2
オフラインかオンラインかを知る必要がありますか?またはどのようなインターネット接続?
tudor.gergely

うん。基本的にオンラインまたはオフライン。
Nilanka Manoj

WebSocket接続を公開するようにAPIを変更できますか?
ヤデホ

回答:


2

方法1:レガシーブラウザAPIを使用する- Navigator.onLine

ブラウザのオンライン状態を返します。プロパティはブール値を返し、trueはオンライン、falseはオフラインを意味します。プロパティは、ネットワークに接続するブラウザーの機能が変更されるたびに更新を送信します。更新は、ユーザーがリンクをクリックしたとき、またはスクリプトがリモートページを要求したときに発生します。たとえば、ユーザーがインターネット接続を失った直後にリンクをクリックすると、プロパティはfalseを返します。

コンポーネントのライフサイクルに追加できます。

Chrome開発ツールを使用して以下のコードを試してください-[ネットワーク]タブで[オンライン]を[オフライン]に切り替えます。

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>


しかし、これはあなたが望むものではないと思います、あなたはリアルタイムの接続バリデーターを望んでいました。

方法2:インターネット接続を使用して確認する

外部インターネット接続が機能している場合に取得できる唯一の確実な確認は、それを使用することです。問題は、コストを最小限に抑えるためにどのサーバーを呼び出す必要あるかです。

これにはインターネット上に多くの解決策があり、204ステータスで応答するエンドポイントはすべて完璧です。例:

  • Googleサーバーへの呼び出し(最もテストされた(?)であるため)
  • キャッシュされたJQueryスクリプトエンドポイントを呼び出す(サーバーがダウンしている場合でも、接続がある限りスクリプトを取得できるはずです)
  • 安定したサーバーから画像をフェッチしてみてください(例:https : //ssl.gstatic.com/gb/images/v1_76783e20.png +日付のタイムスタンプでキャッシュを防止)

IMO、このReactアプリをサーバーで実行している場合、独自のサーバーを呼び出すのが最も理にかなって/favicon.icoいます。接続を確認するためにをロードするリクエストを呼び出すことができます。

(独自のサーバーを呼び出す)このアイデアは、次のような多くのライブラリによって実装されたOfflineis-reachableと広く社会全体で使用されています。自分ですべてを書きたくない場合は、それらを使用できます。(個人的には、is-reachableシンプルなNPMパッケージが好きです。)

例:

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

テストサーバー接続の編集

私はあなたが現在持っているものはすでに問題ないと信じています、それが正しいエンドポイントを呼び出していることを確認してください。


同様のSOの質問:


8

https://developer.mozilla.org/en-US/docs/Web/API/Window/offline_eventを使用できます

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

そしてhttps://developer.mozilla.org/en-US/docs/Web/API/Window/online_event あなたがオンラインに戻っているときチェックします

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

私の状況でLANを外部から切断できます:(
Nilanka Manoj

2

カスタムフックをセットアップする

オンライン、オフラインのイベントでフックを設定します。次に、状態を更新して返します。このようにして、インポートを使用してアプリの任意の場所で使用できます。必ずreturn関数でクリーンアップしてください。そうしないと、コンポーネントがフックマウントを使用するたびに、より多くのイベントリスナーが追加されます。

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
}

これを使用するには、上記のフックをインポートして、次のように呼び出します。

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

私の状況でLANを外部から切断できます:(
Nilanka Manoj

3
firebaseなどのソケットサービスを使用する場合は、インターネット接続をキャプチャする組み込みイベントを使用できます。
ジョーロイド

提案されたアプローチのコードの基本的な骨組みを提供できますか
Nilanka Manoj

2

すべてのサブコンポーネント間で共有するコンポーネントを作成できます

中古:

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

}

イベントリスナーを削除するのを忘れましたか?
gautamits
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.