监听BLE特征时丢失Context最新状态的问题求助
解决BLE监听回调无法获取Context最新状态的问题
问题根源
你的问题本质是闭包陷阱:onUpdate回调在组件初始渲染时被创建,捕获了当时的currentMatch和currentPerson值。后续MatchProvider中的状态更新时,这个回调并没有重新生成,仍然使用旧闭包中的状态值,导致无法获取最新状态。
解决方案
方案1:用useRef保存状态的最新引用
通过useRef维护状态的实时引用,让回调总能拿到最新值:
import { useContext, useRef, useEffect } from 'react'; // BluetoothProvider组件内部逻辑 const { currentMatch, currentPerson } = useContext(MatchDataContext); const matchRef = useRef(currentMatch); const personRef = useRef(currentPerson); // 监听状态变化,实时更新ref的引用 useEffect(() => { matchRef.current = currentMatch; personRef.current = currentPerson; }, [currentMatch, currentPerson]); // 检查状态的函数,改用ref.current获取最新值 const updating = () => { if (matchRef.current != null && personRef.current != null) { console.log('found person') } else { console.log('no person') } } const onUpdate = (error: BleError | null, characteristic: Characteristic | null) => { updating(); } // 用useEffect管理BLE监听的生命周期,避免内存泄漏 useEffect(() => { const subscription = device.monitorCharacteristicForService( service.uuid, characteristic.uuid, onUpdate ); // 组件卸载或依赖变化时取消监听 return () => { subscription.remove(); }; }, [device, service.uuid, characteristic.uuid]);
方案2:用useCallback和useEffect重新注册回调
让onUpdate回调在状态变化时重新生成,并同步更新BLE监听的注册:
import { useContext, useCallback, useEffect } from 'react'; // BluetoothProvider组件内部逻辑 const { currentMatch, currentPerson } = useContext(MatchDataContext); // 用useCallback包裹回调,依赖包含状态值,状态变化时重新生成回调 const onUpdate = useCallback((error: BleError | null, characteristic: Characteristic | null) => { if (currentMatch != null && currentPerson != null) { console.log('found person') } else { console.log('no person') } }, [currentMatch, currentPerson]); // 用useEffect管理监听,依赖包含onUpdate,回调变化时重新注册 useEffect(() => { const subscription = device.monitorCharacteristicForService( service.uuid, characteristic.uuid, onUpdate ); return () => { subscription.remove(); }; }, [device, service.uuid, characteristic.uuid, onUpdate]);
关键注意事项
- 必须通过
useEffect管理BLE监听的生命周期,确保组件卸载或依赖变化时取消旧监听,避免内存泄漏和无效回调残留。 - 方案1适合状态频繁变化的场景,无需频繁重新注册监听;方案2通过重新注册回调保证上下文同步,逻辑更直接。
内容的提问来源于stack exchange,提问作者Leon
相关产品推荐
相关产品推荐

