You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将依赖全局变量的蓝牙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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 09:36:02