首页 > 解决方案 > 如何在不使用状态数组的情况下将 React Native 手机传感器数据保存到数组中(超出最大更新深度)?

问题描述

我在弄清楚如何在 React Native 中处理传感器数据时遇到了一些麻烦。我的目标是在有限的时间内(比如说 10 秒)获取手机传感器数据,并在完成后将获得的列表保存到本地数据库。然而,将新的陀螺仪值推送到状态数组是一种选择,但在那里获得最大更新深度超出错误。代码如下。

import React from 'react';
import {
  StyleSheet,
  View,
  Text,
  Dimensions,
} from 'react-native';
import { Gyroscope } from 'expo-sensors';
import { Button } from "native-base";
import CountDown from 'react-native-countdown-component';
import UUID from 'pure-uuid';
import {insertGyroData} from './measureService';

const SAMPLING_RATE = 20; // defaults to 20ms

export class Measure extends React.Component {
  state = {
    gyroscopeData: {},
    measuringStarted: false,
    x_gyro: [0],
    y_gyro: [0],
    z_gyro: [0]
  };

  componentDidMount() {
    this.toggleGyroscope();
  }

  componentWillUnmount() {
    this.unsubscribeAccelerometer();
  }

  toggleGyroscope = () => {
    if (this.gyroscopeSubscription) {
      this.unsubscribeAccelerometer();
    } else {
      this.gyroscopeSubscribe();
    }
  };

  gyroscopeSubscribe = () => {
    Gyroscope.setUpdateInterval(20);
    this.gyroscopeSubscription = Gyroscope.addListener(gyroscopeData => {
      this.setState({ gyroscopeData });
    });
  };

  unsubscribeAccelerometer = () => {
    this.gyroscopeSubscription && this.gyroscopeSubscription.remove();
    this.gyroscopeSubscription = null;
  };

  referenceMeasurementCompleted = async (x, y, z) => {
    this.setState({ measuringStarted: false });
      const uuid = new UUID(4).format();
      await insertGyroData([uuid, 'admin', '12345', x.toString(), y.toString(), z.toString()]);
    alert('Reference measurements completed');
  };

  render() {
    let { x, y, z } = this.state.gyroscopeData;
    const { x_gyro, y_gyro, z_gyro } = this.state;
    if (this.state.measuringStarted) {
      this.setState(({ x_gyro: [...x_gyro, x], y_gyro: [...y_gyro, y], z_gyro: [...z_gyro, z] }));

      return (
        <View style={styles.container}>
          <Text>Gyroscope:</Text>
          <Text>
            x: {round(x)} y: {round(y)} z: {round(z)}
          </Text>
          <Text>Time spent:</Text>
          <CountDown
            until={5}
            size={30}
            onFinish={() => this.referenceMeasurementCompleted(x_gyro, y_gyro, z_gyro)}
            digitStyle={{ backgroundColor: '#FFF' }}
            digitTxtStyle={{ color: '#00c9ff' }}
            timeToShow={['M', 'S']}
            timeLabels={{ m: 'MM', s: 'SS' }}
          />
        </View>
      );
    } else {
      return (
        <View style={styles.container}>
          <Button
            rounded
            primary
            onPress={() => this.setState({ measuringStarted: true })}
          >
            <Text style={styles.buttonText}>Start reference measurements</Text>
          </Button>
        </View>
      );
    }
  }
}

function round(n) {
  if (!n) {
    return 0;
  }

  return Math.floor(n * 100) / 100;
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    height: Dimensions.get('window').height,
    backgroundColor: 'white',
    alignItems: 'center',
    justifyContent: 'center'
  },
  buttonText: {
    color: 'white',
    fontSize: 20,
    paddingHorizontal: 10,
  },
});

使用当前的解决方案,我得到最大深度更新超出错误 请帮助!

标签: react-nativereact-state-managementreact-statereact-native-sensors

解决方案


错误显然来自此块,因为您正在更改渲染内部的状态。

if (this.state.measuringStarted) {
  this.setState(({ x_gyro: [...x_gyro, x], y_gyro: [...y_gyro, y], z_gyro: [...z_gyro, z] }));

}

您可以尝试的一种方法是更新状态

componentDidUpdate(prevProps,prevState){}

但请注意它不会导致Maximum Stack Reached 错误。使用适当的条件语句,您可以将状态设置为新数据而无需无限递归。


推荐阅读