根据外部 Internet 连接动态更改状态 - React(离线/在线)
Posted
技术标签:
【中文标题】根据外部 Internet 连接动态更改状态 - React(离线/在线)【英文标题】:Change state dynamically based on the external Internet connectivity - React (offline/online) 【发布时间】:2020-07-11 16:19:52 【问题描述】:我有一个 React 组件,其中包括 Internet 连接的可用性标志。 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 />;
已编辑:
正在寻找能够检测外部 Internet 连接的解决方案。该设备可以连接到没有外部连接的 LAN。所以,它被认为是离线的。 当且仅当设备可以访问外部互联网资源时才考虑在线。
【问题讨论】:
您需要知道您是离线还是在线?或什么互联网连接? 是的。基本上在线或离线。 你能改变 API 让它暴露一个 websocket 连接吗? 【参考方案1】:您可以使用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.");
);
【讨论】:
在我的情况下局域网可以外部断开:(【参考方案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
【讨论】:
在我的情况下局域网可以外部断开:( 如果您使用像 firebase 这样的套接字服务,您可以使用捕获互联网连接的内置事件。 您能否提供建议方法的基本代码框架。【参考方案3】:您可以创建一个组件在所有子组件之间共享
使用:
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>
【讨论】:
你忘了移除事件监听器?【参考方案4】:方法一:使用旧版浏览器 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
来检查连接。
这个想法(调用你自己的服务器)已经被许多库实现了,例如Offline
、is-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>
);
我相信你目前拥有的已经很好,只要确保它调用了正确的端点。
类似的 SO 问题:
Detect the Internet connection is offline? Detect network connection in React Redux app - if offline, hide component from user https://***.com/Questions/3181080/How-To-Detect-Online-Offline-Event-Cross-Browser【讨论】:
以上是关于根据外部 Internet 连接动态更改状态 - React(离线/在线)的主要内容,如果未能解决你的问题,请参考以下文章