繁体   English   中英

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

[英]Change state dynamically based on the external Internet connectivity - React (offline/online)

我有一个 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 连接的解决方案。 设备可以连接到没有外部连接的 LAN。 所以,它被认为是离线的。 当且仅当设备可以访问外部 Internet 资源时才考虑在线。

您可以使用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.");
});

方法一:使用旧版浏览器 API - Navigator.onLine

返回浏览器的在线状态。 该属性返回一个布尔值,true 表示在线,false 表示离线。 只要浏览器连接到网络的能力发生变化,该属性就会发送更新。 当用户点击链接或脚本请求远程页面时,就会发生更新。 例如,当用户在失去 Internet 连接后不久单击链接时,该属性应返回 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 状态响应的端点都是完美的,例如:

  • 调用谷歌服务器(因为它是最久经考验的(?))
  • 调用其缓存的 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>
    );
  }
}

编辑测试服务器连接

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


类似的问题:

设置自定义钩子

设置与在线、离线事件的挂钩。 然后更新一个状态并返回它。 通过这种方式,您可以通过导入在应用程序的任何位置使用它。 确保使用返回函数进行清理。 如果不这样做,每次使用钩子挂载的组件都会添加越来越多的事件侦听器。

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

您可以创建一个组件以在所有子组件之间共享

用过的:

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

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM