根据外部Internet连接动态更改状态-React(离线/在线)


9

我有一个React组件,其中包括Internet连接的可用性标志。UI元素必须根据状态实时动态更改。同样,功能随着标志的改变而有所不同。

我当前的实现使用间隔每秒钟使用Axios轮询一次远程API,并相应地更新状态。我正在寻找一种更精细,更有效的方法来执行此任务,以最小的计算成本消除状态的1秒错误。仅当设备具有外部Internet连接时才视为在线

当前实施:

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

编辑:

寻找一种能够检测外部Internet连接的解决方案。设备可以连接到没有外部连接的局域网。因此,它被认为是脱机的。仅当设备可以访问外部Internet资源时,才考虑联机。


2
您需要知道您是离线还是在线吗?或什么互联网连接?
tudor.gergely

是的 基本上在线或离线。
Nilanka Manoj

您可以更改API以使其公开websocket连接吗?
yadejo

Answers:


2

方法一:使用旧版浏览器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>


但是,我认为这不是您想要的,您需要一个实时连接验证器。

方法二:使用互联网检查互联网连接

如果外部互联网连接正常,您可以获得的唯一肯定的确认是使用它。问题是您应该调用哪台服务器以最小化成本?

互联网上有许多解决方案,任何以204状态快速响应的端点都是完美的,例如:

  • 呼叫Google服务器(因为它是经过最严格测试的(?))
  • 调用其缓存的JQuery脚本端点(因此,即使服务器已关闭,只要有连接,您仍然应该能够获取脚本)
  • 尝试从稳定的服务器获取图像(例如:https : //ssl.gstatic.com/gb/images/v1_76783e20.png +日期时间戳以防止缓存)

IMO,如果您正在服务器上运行此React应用程序,则最有必要调用自己的服务器,您可以调用一个请求以加载您的请求/favicon.ico以检查连接。

(调用自己的服务器)这个想法已经由许多库实现,例如Offlineis-reachable,并在整个社区中得到广泛使用。如果您不想自己编写所有内容,则可以使用它们。(我个人很喜欢NPM软件包is-reachable的简单性。)

例:

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

编辑测试服务器连接

我相信您目前所拥有的已经很好,只需确保它调用了正确的端点即可。


类似的问题:


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/zh-CN/docs/Web/API/Window/online_event 用于检查您何时重新在线

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

在我的情况下,LAN可以从外部断开连接:(
Nilanka Manoj

2

设置自定义挂钩

设置在线,离线事件的钩子。然后更新状态并返回它。这样,您可以在导入的任何位置将其用于应用程序中。确保使用返回功能进行清理。如果您不这样做,则每次使用挂钩安装组件时,都会添加越来越多的事件侦听器。

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之类的套接字服务,则可以使用捕获Internet连接的内置事件。
Joe Lloyd

您可以提供建议方法的基本代码框架吗?
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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.