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

React Native iOS端useState配合回调函数失效问题求助

React Native iOS端useState更新后BLE扫描回调失效问题解决

问题场景

在iOS 17、Xcode 15、React 18.2.0、React Native 0.72.7环境下,使用react-native-ble-plx的startDeviceScan(或自定义searchDevices函数)时,首次调用setState更新设备列表后,扫描回调不再触发,Android端无此异常。

核心原因

iOS端BLE扫描回调受组件渲染周期影响:当useState更新触发组件重渲染后,原回调因闭包捕获旧变量引用,导致扫描逻辑被意外终止;或react-native-ble-plx在iOS端的扫描实例未在重渲染后正确保留引用。

解决方案

方案1:用useRef保存稳定的回调与管理器引用

通过useRef存储回调和BleManager实例,避免组件重渲染时引用丢失:

import { useState, useEffect, useRef } from 'react';
import { Button } from 'react-native';
import { BleManager } from 'react-native-ble-plx';

const BleScanner = () => {
  const [devices, setDevices] = useState([]);
  // 用useRef保存BleManager实例,避免重复创建
  const managerRef = useRef(new BleManager());
  // 存储稳定的扫描回调引用
  const scanCallbackRef = useRef((device) => {
    console.info('Triggered');
    // 函数式更新,避免闭包捕获旧状态
    setDevices(prev => {
      if (!prev.some(d => d.id === device.id)) {
        return [...prev, device];
      }
      return prev;
    });
  });

  useEffect(() => {
    console.log('devices', devices);
  }, [devices]);

  const searchDevicesPress = () => {
    // 先停止已有扫描
    managerRef.current.stopDeviceScan();
    // 启动扫描并使用稳定的回调
    managerRef.current.startDeviceScan(null, null, (error, device) => {
      if (error) {
        console.error(error);
        return;
      }
      if (device) scanCallbackRef.current(device);
    });
  };

  return <Button onPress={searchDevicesPress} title="Search" />;
};

export default BleScanner;

方案2:用useCallback控制扫描函数引用+生命周期清理

通过useCallback保证扫描函数引用稳定,同时在组件卸载或重新扫描时清理旧任务:

import { useState, useEffect, useCallback } from 'react';
import { Button } from 'react-native';
import { BleManager } from 'react-native-ble-plx';

const BleScanner = () => {
  const [devices, setDevices] = useState([]);
  const manager = new BleManager();

  // 组件卸载时停止扫描
  useEffect(() => {
    return () => manager.stopDeviceScan();
  }, [manager]);

  useEffect(() => {
    console.log('devices', devices);
  }, [devices]);

  // 用useCallback保证函数引用稳定
  const searchDevicesPress = useCallback(() => {
    manager.stopDeviceScan();
    manager.startDeviceScan(null, null, (error, device) => {
      if (error) {
        console.error(error);
        return;
      }
      if (device) {
        console.info('Triggered');
        setDevices(prev => {
          if (!prev.some(d => d.id === device.id)) {
            return [...prev, device];
          }
          return prev;
        });
      }
    });
  }, [manager]);

  return <Button onPress={searchDevicesPress} title="Search" />;
};

export default BleScanner;

额外排查项

  • 确认iOS权限配置:Info.plist中需添加NSBluetoothAlwaysUsageDescription和NSBluetoothPeripheralUsageDescription权限描述
  • 更新依赖:将react-native-ble-plx升级到支持iOS 17的最新版本

内容的提问来源于stack exchange,提问作者Jogy Felix

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 21:18:34