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

React Native接收BLE数据时实时图表不显示问题排查

问题定位

你的图表完全不显示是4个代码逻辑错误共同导致的,没有玄学问题:

  • 渲染逻辑写反:initialState中isLoading默认值是false,render方法里写的是this.state.isLoading ? 渲染图表容器 : 返回null,等于组件加载完永远返回空节点,根本不会挂载Chart组件,这是最直接的不显示原因。
  • BLE数据链路断了:你在DeviceScreen里只完成了设备连接和服务发现,没有订阅对应BLE特征值的实时通知,也没有把收到的hr值作为属性传给ChartScreen,写的<ChartScreen chartdata />是无效空属性,ChartScreen里引用的全局hr不是响应式变量,值变了组件根本不会触发更新。
  • 生命周期用错:getDerivedStateFromProps的标准入参是(nextProps, prevState),你写的入参不对,而且每次触发都直接把flow覆盖为[hr]单元素数组,就算拿到了新值也存不下历史数据,不可能实现滚动实时曲线效果。
  • 初始值引用风险:initialState里直接引用未经过组件传入的hr,如果hr不是显式导入的全局常量,组件初始化就会抛出引用错误。
修复方案

1. 改造DeviceScreen,补全BLE特征订阅逻辑,把实时hr传给图表组件

你现在只拿到了设备服务列表,没有监听特征值变化,补上对应逻辑:

// 新增hr值的状态存储
const [hr, setHr] = useState<number>(0);

useEffect(() => {
  const getDeviceInformations = async () => {
    // 连接设备
    const connectedDevice = await device.connect();
    setIsConnected(true);
    // 发现服务和特征
    const allServicesAndCharacteristics = await connectedDevice.discoverAllServicesAndCharacteristics();
    const discoveredServices = await allServicesAndCharacteristics.services();
    setServices(discoveredServices);

    // 补全特征订阅逻辑,UUID替换成你自己设备对应的心率服务、特征UUID
    const hrService = await connectedDevice.getService("你的心率服务UUID");
    const hrCharacteristic = await hrService.getCharacteristic("你的心率特征UUID");
    // 监听特征值实时变化
    hrCharacteristic.monitor((error, characteristic) => {
      if (error || !characteristic) return;
      // 按照硬件协议解析hr数值,以下为示例解析逻辑,替换成你设备对应的解析规则
      const realTimeHr = characteristic.readUInt16(0) || 0;
      setHr(realTimeHr);
    });

    // 原有权限申请逻辑保留
    PermissionsAndroid.request(
      PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
      {
        title: 'Permission Localisation Bluetooth',
        message: 'Requirement for Bluetooth',
        buttonNeutral: 'Later',
        buttonNegative: 'Cancel',
        buttonPositive: 'OK',
      }
    );     
  };  
  getDeviceInformations();

  // 原有断开监听、卸载返回逻辑保留
  device.onDisconnected(() => {
    navigation.navigate('Home');
  });

  return () => {
    disconnectDevice();
  };
}, [device, disconnectDevice, navigation]);

// 渲染部分把hr作为有效属性传给ChartScreen,删掉空的chartdata属性
<View>
  <ChartScreen hr={hr} />
</View>

2. 重写ChartScreen逻辑,删掉错误的生命周期方法

import React, { Component } from 'react';
import { Dimensions, StyleSheet, View, ActivityIndicator } from 'react-native';
// 自行导入你项目里的Chart、ScreenContainer组件

const width = Dimensions.get('window').width;
const height = Math.floor((Dimensions.get('window').height - 150) / 3);
const slotsPerWidth = 100;
// 最多缓存100个数据点,满了就删除最旧的点实现滚动效果
const MAX_DATA_POINTS = 100;

class ChartScreen extends Component {
  state = {
    flow: [],
    isLoading: true,
  };

  // 监听传入的hr变化,追加到数据数组
  componentDidUpdate(prevProps) {
    if (prevProps.hr !== this.props.hr && this.props.hr !== undefined) {
      this.setState(prevState => {
        const newFlow = [...prevState.flow, this.props.hr];
        if (newFlow.length > MAX_DATA_POINTS) newFlow.shift();
        return {
          flow: newFlow,
          isLoading: false
        }
      })
    }
  }
  
  render() {
    const { flow } = this.state;
    // 加载中显示loading
    if (this.state.isLoading) {
      return (
        <ScreenContainer>
          <View style={styles.main}>
            <ActivityIndicator size="large" color="#fff"/>
          </View>
        </ScreenContainer>
      )
    }

    // 数据就绪渲染图表
    return (
      <ScreenContainer>
        <View style={styles.main}>
          <Chart
            key="flow"
            data={flow}
            maxValue={1900}
            minValue={1750}
            slotsPerWidth={slotsPerWidth}
            width={width}
            height={height}
            marginBottom={20}
            lineColor="rgba(95, 92, 1, 1)"
            lineThickness={2}
            chartBackground="#17204d"
            horizontalGridLinesCount={5}
            gridColor="rgba(65, 95, 93, .4)"
            gridThickness={1}
            unit="ml"
            axisTooClose={10}
            labelsColor="rgba(255, 255, 255, 0.8)"
            labelsFontSize={12}
            marginLeft={60}
            labelsMarginLeft={15}
          />
        </View>
      </ScreenContainer>
    )
  } 
}
    
const styles = StyleSheet.create({
  main: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center'
  },
});

export default ChartScreen;
额外检查项
  • 确认你用的Chart组件的data入参要求:如果要求传入带x/y坐标的对象数组,需要在追加数据时补上x轴序号。
  • BLE特征值解析逻辑必须和硬件厂商给出的协议对齐,如果解析出的数值超出你设置的minValue/maxValue范围,图表也不会正常画线。
  • 安卓12及以上版本需要额外申请BLUETOOTH_SCAN、BLUETOOTH_CONNECT权限,否则会出现低版本能收数据、高版本收不到的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 22:12:50