Reputation: 61
I have a React-Native app that uses the library react-native-sensors to access the mobile device's accelerometer data (x, y, and z-axis). The react-native-sensors library utilizes RxJS observables, something I am unfamiliar with.
In an earlier version of the app, the App component would set its own state to the device's live accelerometer data. This occurred inside the component's constructor function, where the accelerometer observable used the subscribe operator to call 'setState'. This approach had the desired effect i.e. the App component's state continued to update at regular intervals as the device moved.
At this stage the App component looked like this:
import React, { Component } from "react";
import { setUpdateIntervalForType, SensorTypes, accelerometer } from "react-native-sensors";
export default class App extends Component {
constructor(props) {
super(props);
setUpdateIntervalForType(SensorTypes.accelerometer, 150);
accelerometer.subscribe(({ x, y, z }) => {
this.setState({ x, y, z }),
error => {
console.log("The sensor is not available");
};
});
this.state = { x: 0, y: 0, z: 0 };
}
render() {
...
...
...
}
}
In order to improve encapsulation and perform better tests I decided to extract the accelerometer observable into a separate file and export it back into the App component. My intention was to export the observable as a function that would return a stream of values i.e. those emitted from the accelerometer. This is where I got stuck. My first attempt to export the observable data looked like this:
Accelerometer.js
import {
setUpdateIntervalForType,
SensorTypes,
accelerometer
} from "react-native-sensors";
export default function AccelerometerData() {
var data;
setUpdateIntervalForType(SensorTypes.accelerometer, 150);
accelerometer.subscribe(({ x, y, z }) => {
data = { x, y, z }
});
return data;
}
I appreciate this approach does not respect the asynchronous nature of RxJS observables. I'm also aware that there are other operators such as 'map' that may help here, but I'm not entirely sure how to implement it in this context.
Upvotes: 0
Views: 898
Reputation: 61
Thanks Fan Cheung. I eventually took this route:
export async function accelerometerData() {
setUpdateIntervalForType(SensorTypes.accelerometer, 150);
return accelerometer;
}
Usage:
async getAccelerometerData() {
const accelerometer = await accelerometerData();
accelerometer.subscribe(({ x, y, z }) => {
this.setState({ x, y, z }),
error => {
console.log("The sensor is not available");
};
});
}
}
Upvotes: 0
Reputation: 11345
You can just return it as an observable and chain it up with a setState wrapped in an Obervable
export default function AccelerometerData() {
var data;
setUpdateIntervalForType(SensorTypes.accelerometer, 150);
return accelerometer
}
Usage
setState(obj)=>
new Observable(obs=>this.setState(obj,()=>obs.next(this.state))
AccelerometerData().pipe(tap(obj=>setState(obj)).subscribe()
Upvotes: 0