如何将依赖全局变量的蓝牙React应用重构为函数式写法?
import { useState, useEffect, useRef, useCallback } from 'react'; export default function App(){ // 解决问题2:用useState存储认证状态,可直接在UI中渲染 const [authenticated, setAuthenticated] = useState(false); // sessionKey、device不需要触发UI更新,用useRef存储更高效,避免不必要重渲染 const sessionKeyRef = useRef(""); const deviceRef = useRef(null); // 解决问题1:监听器定义在组件内部,通过闭包/引用直接访问状态,无需额外传参 const btListener = useCallback((data) => { if(authenticated){ decryptPacket(data, sessionKeyRef.current); } else { sessionKeyRef.current = finishAuthentication(data); setAuthenticated(true); } }, [authenticated]); useEffect(() => { // 蓝牙初始化逻辑 const device = getBTDevice(); deviceRef.current = device; registerBTListener(device, btListener); startAuthentication(device); // 清理逻辑:组件卸载时移除监听器,避免内存泄漏 return () => { // 按实际蓝牙SDK接口替换为对应的注销方法即可 unregisterBTListener(device, btListener); } }, [btListener]); return <> {/* 直接读取authenticated状态展示认证情况 */} <span>蓝牙状态:{authenticated ? "已认证" : "认证中"}</span> ...其余UI代码... </> }
优化可选方案
如果蓝牙监听器注册开销较高,不想每次authenticated变化都重新注册,可以用ref同步状态副本,避免依赖变动:
const [authenticated, setAuthenticated] = useState(false); const authenticatedRef = useRef(false); // 统一更新方法,同时同步state和ref的值 const updateAuthenticated = (val) => { setAuthenticated(val); authenticatedRef.current = val; } const btListener = useCallback((data) => { // 读取ref的实时值,不需要依赖authenticated状态 if(authenticatedRef.current){ decryptPacket(data, sessionKeyRef.current); } else { sessionKeyRef.current = finishAuthentication(data); updateAuthenticated(true); } }, []); // 无依赖,只会初始化一次,避免重复注册监听器
内容的提问来源于stack exchange,提问作者T3db0t
相关产品推荐
相关产品推荐

