react-native-background-timer, null is not an object - reactjs

I've got an error using react-native-background-timer. I would be appreciate it if you could help me solve this problem.
I'm developing a mobile app on Expo Snack, and I now want to realize the auto-delete-account function: when an account is created and not being verified for 5 minutes, it will be deleted automatically.
So, I searched about background timer and I found the library below.
https://github.com/ocetnik/react-native-background-timer
However, I wasn't able to achieve it because of the error below
(3:2693) null is not an object (evaluating 'o.setTimeout')
and this is my code
import React, { Component } from 'react';
import { View, Text, TouchableOpacity, Platform } from 'react-native';
import BackgroundTimer from 'react-native-background-timer';
let counter = 0;
let timer = null;
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
second: 0,
};
}
_interval: any;
onStart = () => {
if (Platform.OS == 'ios') {
BackgroundTimer.start();
}
this._interval = BackgroundTimer.setInterval(() => {
this.setState({
second: this.state.second + 1,
});
}, 1000);
};
onPause = () => {
BackgroundTimer.clearInterval(this._interval);
};
onReset = () => {
this.setState({
second: 0,
});
BackgroundTimer.clearInterval(this._interval);
};
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<TouchableOpacity onPress={this.onStart}>
<Text>start</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.onPause}>
<Text>pause</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.onReset}>
<Text>reset</Text>
</TouchableOpacity>
<Text>{this.state.second}</Text>
</View>
);
}
}
I followed a tutorial of this guy
https://medium.com/#loons.create/how-to-setup-react-native-background-timer-22263d655847
The equipped function, setInterval of javascript and etc. of course works fine as a timer, but actually they don't work behind in react native.
What am I missing, or is this an issue inside this library( I suppose so )? If so, please tell me an available version of this library; I use the latest version, 2.2.0, and React v35.0.0
Thank you

You cannot use "react-native-background-timer" with Expo on managed workflow. This library needs to compile some native code.
Instead, you should take a took to Expo BackgroundFetch which is doing almost the same thing.
https://docs.expo.io/versions/latest/sdk/background-fetch/
Using Expo components, you don't need to eject or compile additional native code.

Related

Invalid hook call in a react function, ImagePicker and ActionSheet

I really need some help with hooks in react native...
I have an ActionSheet which onPress one of the options a camera feature should open with "useCamera" function.
The "useCamera" is in another function(on another file),
using the library "ImagePicker". (specific "ImagePicker.launchCamera")
the "ImagePicker.launchCamera" set the fileUri in the callback while the function return nothing.
So to access the fileUri, I tried to use useState Hook but I get "ERROR: Invalid Hook call.Hooks can only be called inside of the body of the function..."
but the hook inside the function bodY!
ActionSheet code:
import {useCamera} from './PhotoHandle';
// export default class EditProfilePic extends React.Component {
function EditProfilePic(props) {
const [ActionSheetRef, setActionSheetRef] = useState(null);
const [fileDate, setFileDate] = useState(null);
return (
<View style={styles.images_container}>
<TouchableOpacity
style={styles.click_edit_icon}
onPress={() => ActionSheetRef.show()}>
<Image style={styles.editIcon} source={editIcon} />
</TouchableOpacity>
<Image source={props.profileSource} style={styles.image} />
<ActionSheet
ref={o => setActionSheetRef(o)}
title={
<Text style={{color: '#000', fontSize: 18}}>
Which one do you like?
</Text>
}
options={['Select from Photos', 'Camera', 'Cancel']}
cancelButtonIndex={2}
destructiveButtonIndex={2}
onPress={index => {
//camera
if (index == 1) {
useCamera()
}
}}
/>
</View>
);
}
LaunchCamera function:
export function useCamera() {
const [fileData, setFileData] = useState(null);
let options = {
storageOptions: {
skipBackup: true,
path: 'images',
},
};
ImagePicker.launchCamera(options, response => {
console.log('coolio' + response);
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
alert(response.customButton);
} else {
setFileData(response.data);
}
});
return fileData;
}
I tried to call useCamera() like "< useCamera / >",
I changed the anonymous function to just a function.
I tried to call useCamera() from other part of the code (not from onPress) .
I tried to use Context,and Redux.
ALL THE SAME ERROR.
please help meee,
Thanks!
I've had this problem before as well what version of React-Native are you using?
React 16.8.0 is the first release to support Hooks. When upgrading, don’t forget to update all packages, including React DOM. React Native supports Hooks since the 0.59 release of React Native.
https://reactjs.org/docs/hooks-intro.html
I see the sign, you call this.setState, it means you are using a class-based component.
a react hook can be used only in a functional component.
You have to convert the component which called LaunchCamera() (it should be renamed useCamera()) to the functional component.

I am working on a project and I need to translate speech into text I used Expo and React-native-voice

I am working on a project and I need to translate speech into text I used Expo and React-native-voice.
**[Unhandled promise rejection: TypeError: null is not an object (evaluating 'Voice.onSpeechStart = null')]
- node_modules\react-native-voice\src\index.js:23:10 in removeAllListeners
- node_modules\promise\setimmediate\core.js:37:14 in tryCallOne
- ... 9 more stack frames
import React from "react";
import { StyleSheet, Text, View, TouchableOpacity } from "react-native";
import Voice from "react-native-voice";
import * as Permissions from "expo-permissions";
export default class App extends React.Component {
constructor() {
super();
this.state = {
results: [],
};
Voice.onSpeechStart = this.onSpeechStart;
Voice.onSpeechRecognized = this.onSpeechRecognized;
Voice.onSpeechEnd = this.onSpeechEnd;
Voice.onSpeechError = this.onSpeechError;
Voice.onSpeechResults = this.onSpeechResults;
Voice.onSpeechPartialResults = this.onSpeechPartialResults;
Voice.onSpeechVolumeChanged = this.onSpeechVolumeChanged;
}
async componentDidMount() {
const {status} = await Permissions.askAsync(
Permissions.AUDIO_RECORDING
);
}
componentWillMount(){
Voice.destroy().then(Voice.removeAllListeners)
}
onSpeechStart = (e)=> {
console.log('onSpeechStart',e);
};
onSpeechRecognized =(e)=>{
console.log('onSpeechRecognized',e);
}
onSpeechEnd = (e)=>{
console.log('onSpeechEnd'+e);
}
onSpeechError =(e)=>{
console.log('onSpeechError');
}
onSpeechResults = e => {
console.log('onSpeechResults'+e);
this.setState({
results: e.value,
});
}
onSpeechPartialResults = e =>{
console.log('onSpeechPartialResults' + e.value);
}
onSpeechVolumeChanged = e =>{
console.log('onSpeechVolumeChanged');
}
_startRecognizing=async()=>{
try{
await Voice.start('en-US')
} catch(e) {
console.error(e);
}
}
_stopRecognizing = async()=>{
try{
await Voice.stop()
}catch(e){
console.error(e);
}
}
render() {
return (
<View style={styles.container}>
<TouchableOpacity
onPress={this._startRecognizing}
style={{
backgroundColor: "green",
height: 40,
width: 100,
marginBottom: 10,
}}
>
<Text style={{
fontSize: 20,
alignSelf: "center"
}}>
Starts
</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={this._stopRecognizing}
style={{
backgroundColor: "red",
height: 40,
width: 100
}}
>
<Text style={{
fontSize: 20,
alignSelf: "center"
}}>
Stop
</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
});
from framework internals**
Update for Expo 41+
With the release of the Expo SDK 41, config plugins were added. The 3.2.0 release of react-native-voice/voice added support for config plugins.
You install the dependency as you normally would
yarn add #react-native-voice/voice
And then you must update your app.json
"expo": {
"plugins": [
[
"#react-native-voice/voice",
{
"microphonePermission": "Allow $(PRODUCT_NAME) to access your microphone",
"speechRecogntionPermission": "Allow $(PRODUCT_NAME) to securely recognize user speech"
}
]
]
}
You will probably need to create a new build as you may get an invariant violation.
You should now read the documentation for usage
—-
Expo 40 and older
Unfortunately react-native-voice is not compatible with Expo.
The reason for this is that Expo abstracts the native iOS and Android code away from you, this makes it quick and easy to make builds and develop but the downside is that you cannot add dependencies that require you to use native code.
react-native-voice requires the use of native code. You can see this by the fact that the installation instructions require you to link the native code. See here for the documentation.
If you wish to use this dependency in your Expo project then you will need to eject it. You can find more info about ejecting, and the pros and cons of doing so on the Expo documentation website here
With Expo SDK42 you can use the react-native-voice plugin, here is what they have in the docs here
I have the same issue developing an react native app with react-native-voice package. I followed every step of the workflow (like instructed in the react-native-voice documentation as well as suggested by other answers), there seems nothing wrong -
expo run:android build successful. Then expo start --dev-client on my android emulator/physical device both throw this error:
[Unhandled promise rejection: TypeError: null is not an object
(evaluating 'Voice.isSpeechAvailable')]
In the end, I found that, one needs to open two terminals in vscode, one terminal running exp start (while connecting to your device), and the other terminal simultaneously runs expo run:android.
The app then is running on the device like a charm!
Hope this helps, and hope someone can explain more on this regarding how react-native/expo test development works?

React native: Undefined is not an object

I'm making a react native app with expo and I'm having some trouble parsing the response data from the api. Below is a sample response from the api and my goal is to retrieve main from the weather array. I can log weather array just fine but when I put state.weather[0].main it throws the undefined object error.
Object {
"clouds": Object {
"all": 20,
},
...,
"weather": Array [
Object {
"description": "few clouds",
"icon": "02d",
"id": 801,
"main": "Clouds",
},
],
}
Below is my code, I fetch from the api on useEffect() hook. At first the logs shows undefined but after fetching it logs correctly except for state.weather[0].main. I just started react native coming from Android, I hope you guys could help me, I'm stuck for a day now. Thanks
const HomeScreen = ({ navigation }) => {
const { state: { defaultCity } } = useContext(CitiesContext);
const { state: { weather }, fetchWeather } = useContext(WeatherContext);
useEffect(() => {
if (defaultCity) {
fetchWeather(defaultCity);
}
}, []);
console.log(weather);
console.log(typeof (weather[0]));
console.log(weather[0]);
console.log(weather[0].main);
return (
<View style={styles.container}>
<LinearGradient
// {...weatherBgProvider[weather.weather.main]}
colors={['#000', '#fff']}
style={styles.gradient}
>
<SafeAreaView
style={{
position: 'relative'
}}
forceInset={{ top: 'always' }}
>
<View style={{ marginTop: Header.HEIGHT, flex: 1 }}>
<Text >{JSON.stringify(state)}</Text>
</View>
</SafeAreaView>
</LinearGradient>
</View>
);
};
If you are trying to log data in your render, you can do it like this:
<View>{This.state.weather[0] && console.log(this.state.weather[0]) }</View>
So you check it to exist before you log data
Hope you get the idea and works for you
update
If your main not working, first try to parse your object into array like this:
first way use lodash (npm i --dev lodash) and import it in your project
Import _ from "lodash";
Const newdata= _.compact(Object.values(yourobject))
And then you can use newdata and i think your problem will be solved
second way use _.mapKeys(yourdata,"id") and put new data in your variable like const newdata
I hope it works

How to create a blinking react View

Can someone help me out how I can create a blink-able react-native component?
So basically, this is what I have done
class Blinkable extends PureComponent {
state = {
blinkComponentVisibility: false
}
blink () {
this.setState({blinkComponentVisibility: ! blinkComponentVisibility})
console.log(this.state)
}
componentDidMount = () => {
setTimeout(() => {this.blink}, 3000)
}
render () {
if (i === currentProgress) {
if (this.state.blinkComponentVisibility) {
progressBarArray.push(
<View
style={{
width: widthOfIndividualBlog,
backgroundColor: colorOfProgressBar,
height: heightOfProgressBar
}}
key={i}
></View>)
}
}
return (
<View>
<View style={{display: 'flex', flexDirection: 'row'}}>{progressBarArray}</View>
</View>
)
}
}
With the above code, I was expecting my component to blink but nothing happens rather I see the following logs in console
RCTLog.js:47 Could not locate shadow view with tag #363, this is
probably caused by a temporary inconsistency between native views and
shadow views
Can someone please help me in figuring out what I could be doing wrong?
this.setState({blinkComponentVisibility: ! blinkComponentVisibility}) should be this.setState({blinkComponentVisibility: ! this.state.blinkComponentVisibility})
and in your set timout you need to call the function
setTimeout(() => this.blink(), 3000)

React Navigation - Custom Header Animation

I am using React Navigation inside React Native App and i created a Custom Header Component for my routes
like this :
const Router = StackNavigator({
Main: {
screen: Main,
navigationOptions: ({navigation}) => ({
header:<Header title="Main"/>
})
},
})
when using a custom header component the native animation not working
i would like to know how can i achieve the animation in the header the same as here https://reactnavigation.org/
TL:DR; found solution to share the animated.Value / interpolation over screens code below.
Animated Custom Header React-native + React navigation
This post was taunting me for some time - I was faced with the same issue. Hopefully this will reach you even if it's couple of months later :D
So first my issue was this, I made a component for custom header like in your example, my target was having one of the StackNavigator pages, have a scrollView which would in turn manipulate the color of the header.
Similar issue, the information exchange between header and page should help you too, here it goes.
Header.js
export class HeaderBar extends Component {
componentWillMount(){
// might be a bit, ehm but worked so if you have tips how to make the code nice feel free to share
let valueToManipulate= new Animated.Value(0);
this.props.navigation.setParams({
valueToManipulate,
customkey: valueToManipulate.interpolate({
inputRange: [0, 150],
outputRange: ['rgba(0,0,0,0)', 'rgba(0,0,0,1)'],
extrapolate: 'clamp',
})
})
}
render () {
... bit of code ...
// important bit for data binding !
if( ! (this.props.navigation.state.params && this.props.navigation.state.params.customkey) ){
return null;
}
/* unless that variable on params exists we do not ! render */
... bit more of code ...
<View style={ floating }>
<Animated.View style={{backgroundColor: this.props.navigation.state.params.customkey }}> /// <<--- typical bind
<View style={{flexDirection: 'row', justifyContent: "space-between"}}>
... and rest of render ...
So this is the header bit, now for the other "fun" part:
HomePage.js
export default class HomePage extends Component<{}> {
... stufff..... :D
render() {
/* this here, again data binding !, do not let render before we have this var in state params ! */
if( !( this.props.navigation.state.params && this.props.navigation.state.params.valueToManipulate ) )
return null;
return (
<ScrollView
style={styles.container}
onScroll={ Animated.event(
[{ nativeEvent: { contentOffset: { y: this.props.navigation.state.params.valueToManipulate } } }], // <-- tadaaa
)}
bounces={false}
scrollEventThrottle={1}
showsVerticalScrollIndicator={false}
showsHorizontalScrollIndicator={false}
>
... moar stuff ...
}
}
And here ! Finally ! A Demo !
Animated Custom Header React-native + React navigation
I published react-navigation-collapsible.
I hope it would be helpful.
https://github.com/benevbright/react-navigation-collapsible

Resources