Skip to content
霞露小伙 — HfWang
On this page

useNetwork

管理网络连接状态的 Hook

武功秘籍

导入和类型声明

ts
import { useEffect, useState } from "react";
import { isObject } from "../utils";

export interface NetworkState {
	since?: Date;
	online?: boolean;
	rtt?: number;
	type?: string;
	downlink?: number;
	saveData?: boolean;
	downlinkMax?: number;
	effectiveType?: string;
}

enum NetworkEventType {
	ONLINE = "online",
	OFFLINE = "offline",
	CHANGE = "change",
}

getConnection

ts
// 获取网络连接
function getConnection() {
	const nav = navigator as any;
	if (!isObject(nav)) return null;
	// 兼容不同浏览器
	return nav.connection || nav.mozConnection || nav.webkitConnection;
}

getConnectionProperty

ts
// 获取网络链接信息
function getConnectionProperty(): NetworkState {
	const c = getConnection();
	if (!c) return {};

	// https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation
	return {
		// 返回了当前连接下评估的往返时延(RTT, round-trip time)
		rtt: c.rtt,
		// 设备用于与网络通信的连接类型, ajax / jsonp / websocket
		type: c.type,
		// 返回用户已在用户代理上设置了减少数据使用量选项
		saveData: c.saveData,
		// 返回以 Mb/s 为单位的有效带宽,并保留该值为 25kb/s 的最接近的整数倍。
		downlink: c.downlink,
		// 返回最大下行链路速度(以兆比特每秒 (Mbps) 为单位)
		downlinkMax: c.downlinkMax,
		// 返回连接的网络类型 “慢速 2g”、“2g”、“3g”或“4g”之一
		effectiveType: c.effectiveType,
	};
}

useNetwork

ts
function useNetwork(): NetworkState {
	const [state, setState] = useState(() => {
		return {
			since: undefined, // 最后改变时间
			online: navigator?.onLine, // 是否有网络
			...getConnectionProperty(),
		};
	});

	useEffect(() => {
		// 网络连接
		const onOnline = () => {
			setState((prevState) => ({
				...prevState,
				online: true,
				since: new Date(),
			}));
		};
		// 网络掉线
		const onOffline = () => {
			setState((prevState) => ({
				...prevState,
				online: false,
				since: new Date(),
			}));
		};
		// 网络状态发生改变
		const onConnectionChange = () => {
			setState((prevState) => ({
				...prevState,
				...getConnectionProperty(),
			}));
		};

		// 组件改在,开启网络连接、掉线监听
		window.addEventListener(NetworkEventType.ONLINE, onOnline);
		window.addEventListener(NetworkEventType.OFFLINE, onOffline);

		// 获取网络信息 api,如果能拿到,开启网络状态变化的监听
		const connection = getConnection();
		connection?.addEventListener(NetworkEventType.CHANGE, onConnectionChange);

		return () => {
			// 组件卸载,移除上面的监听
			window.removeEventListener(NetworkEventType.ONLINE, onOnline);
			window.removeEventListener(NetworkEventType.OFFLINE, onOffline);
			connection?.removeEventListener(NetworkEventType.CHANGE, onConnectionChange);
		};
	}, []);

	return state;
}

export default useNetwork;

本站中引用到的其他资料,如有侵权,请联系本人删除