如何在React中可靠检测浏览器隐身模式?
可靠检测浏览器隐身模式的React自定义Hook方案
之前通过localStorage/sessionStorage检测的问题在于,像Firefox隐私浏览模式这类场景下,存储API是完全可用的,所以会出现误判。下面是几个适配多浏览器的可靠检测方案,结合React自定义Hook实现:
方案1:利用IndexedDB存储限制(适配Chromium系浏览器)
Chromium内核的浏览器(Chrome、Edge等)在隐身模式下,IndexedDB的存储空间被限制为0,尝试创建数据库会抛出错误。
import { useState, useEffect } from 'react'; const useIncognitoDetector = () => { const [isIncognito, setIsIncognito] = useState(null); useEffect(() => { const checkIncognito = async () => { try { // 尝试创建IndexedDB测试数据库 const request = indexedDB.open('IncognitoTestDB'); await new Promise((resolve, reject) => { request.onupgradeneeded = resolve; request.onerror = reject; request.onsuccess = resolve; }); // 能正常创建则不是隐身模式 setIsIncognito(false); // 清理测试数据库 indexedDB.deleteDatabase('IncognitoTestDB'); } catch (e) { // 创建失败则判定为隐身模式 setIsIncognito(true); } }; checkIncognito(); }, []); return isIncognito; }; export default useIncognitoDetector;
方案2:FileSystem API检测(适配Safari)
Safari的隐身模式下无法通过FileSystem API获取可写的文件系统,会直接拒绝请求。
import { useState, useEffect } from 'react'; const useIncognitoDetector = () => { const [isIncognito, setIsIncognito] = useState(null); useEffect(() => { const checkIncognito = async () => { if (!window.showOpenFilePicker) { // 不支持该API的浏览器,降级为非隐身判定 setIsIncognito(false); return; } try { // 尝试请求文件系统访问权限 await window.showOpenFilePicker({ type: [] }); setIsIncognito(false); } catch (e) { // Safari隐身模式下会抛出NotAllowedError if (e.name === 'NotAllowedError') { setIsIncognito(true); } else { setIsIncognito(false); } } }; checkIncognito(); }, []); return isIncognito; }; export default useIncognitoDetector;
方案3:多方法综合检测(全局兼容)
结合多种检测手段,覆盖不同浏览器的行为差异,提升检测准确率:
import { useState, useEffect } from 'react'; const useIncognitoDetector = () => { const [isIncognito, setIsIncognito] = useState(null); useEffect(() => { const checkIncognito = async () => { let result = false; // 第一步:检测Chromium系IndexedDB限制 try { const request = indexedDB.open('IncognitoTestDB'); await new Promise((resolve, reject) => { request.onupgradeneeded = resolve; request.onerror = reject; request.onsuccess = resolve; }); indexedDB.deleteDatabase('IncognitoTestDB'); } catch (e) { result = true; } // 第二步:检测Safari FileSystem限制(若第一步未判定为隐身) if (!result && window.showOpenFilePicker) { try { await window.showOpenFilePicker({ type: [] }); } catch (e) { if (e.name === 'NotAllowedError') { result = true; } } } // 第三步:降级检测localStorage(仅作为补充) if (!result) { try { localStorage.setItem('test_incognito', 'test'); localStorage.removeItem('test_incognito'); } catch (e) { result = true; } } setIsIncognito(result); }; checkIncognito(); }, []); return isIncognito; }; export default useIncognitoDetector;
使用说明
在React组件中直接调用Hook即可:
function App() { const isIncognito = useIncognitoDetector(); return ( <div> {isIncognito === null ? '检测中...' : isIncognito ? '当前处于隐身模式' : '当前未处于隐身模式'} </div> ); }
注意:所有检测方法都无法做到100%精准(浏览器厂商可能随时修改隐私模式的行为),但综合检测能覆盖绝大多数主流浏览器的场景。
内容的提问来源于stack exchange,提问作者Richardson
相关产品推荐
相关产品推荐

