setTimeout in React Native

I'm trying to load a splash screen for an iOS app built in React Native. I'm trying to accomplish this through class states and then a setTimeout function as follows:

class CowtanApp extends Component {
constructor(props){
super(props);
this.state = {
timePassed: false
};
}


render() {
setTimeout(function(){this.setState({timePassed: true})}, 1000);
if (!this.state.timePassed){
return <LoadingPage/>;
}else{
return (
<NavigatorIOS
style = {styles.container}
initialRoute = {{
component: LoginPage,
title: 'Sign In',
}}/>
);
}
}
}

The loading page works for a second, and then I guess when setTimeout tries to change the state to true, my program crashes: 'undefined is not an object (evaluating this.setState)'. I've been going at this for a couple of hours, any ideas on how to fix it?

245489 次浏览

Write a new function for settimeout. Pls try this.

class CowtanApp extends Component {
constructor(props){
super(props);
this.state = {
timePassed: false
};
}


componentDidMount() {
this.setTimeout( () => {
this.setTimePassed();
},1000);
}


setTimePassed() {
this.setState({timePassed: true});
}




render() {


if (!this.state.timePassed){
return <LoadingPage/>;
}else{
return (
<NavigatorIOS
style = {styles.container}
initialRoute = \{\{
component: LoginPage,
title: 'Sign In',
}}/>
);
}
}
}

Classic javascript mistake.

setTimeout(function(){this.setState({timePassed: true})}, 1000)

When setTimeout runs this.setState, this is no longer CowtanApp, but window. If you define the function with the => notation, es6 will auto-bind this.

setTimeout(() => {this.setState({timePassed: true})}, 1000)

Alternatively, you could use a let that = this; at the top of your render, then switch your references to use the local variable.

render() {
let that = this;
setTimeout(function(){that.setState({timePassed: true})}, 1000);

If not working, use bind.

setTimeout(
function() {
this.setState({timePassed: true});
}
.bind(this),
1000
);

You can bind this to your function by adding .bind(this) directly to the end of your function definition. You would rewrite your code block as:

setTimeout(function () {
this.setState({ timePassed: true });
}.bind(this), 1000);

Change this code:

setTimeout(function(){this.setState({timePassed: true})}, 1000);

to the following:

setTimeout(()=>{this.setState({timePassed: true})}, 1000);

On ReactNative .53, the following works for me:

 this.timeoutCheck = setTimeout(() => {
this.setTimePassed();
}, 400);

'setTimeout' is the ReactNative library function.
'this.timeoutCheck' is my variable to hold the time out object.
'this.setTimePassed' is my function to invoke at the time out.

Same as above, might help some people.

setTimeout(() => {
if (pushToken!=null && deviceId!=null) {
console.log("pushToken & OS ");
this.setState({ pushToken: pushToken});
this.setState({ deviceId: deviceId });
console.log("pushToken & OS "+pushToken+"\n"+deviceId);
}
}, 1000);

There looks to be an issue when the time of the phone/emulator is different to the one of the server (where react-native packager is running). In my case there was a 1 minute difference between the time of the phone and the computer. After synchronizing them (didn't do anything fancy, the phone was set on manual time, and I just set it to use the network(sim) provided time), everything worked fine. This github issue helped me find the problem.

Never call setState inside render method

You should never ever call setState inside the render method. Why? calling setState eventually fires the render method again. That means you are calling setState (mentioned in your render block) in a loop that would never end. The correct way to do that is by using componentDidMount hook in React, like so:

class CowtanApp extends Component {
state = {
timePassed: false
}


componentDidMount () {
setTimeout(() => this.setState({timePassed: true}), 1000)
}


render () {
return this.state.timePassed ? (
<NavigatorIOS
style = {styles.container}
initialRoute = \{\{
component: LoginPage,
title: 'Sign In',
}}/>
) : <LoadingPage/>
}
}

PS Use ternary operators for cleaner, shorter and readable code.

const getData = () => {
// some functionality
}


const that = this;
setTimeout(() => {
// write your functions
that.getData()
},6000);

Simple, Settimout function get triggered after 6000 milliseonds

In case anyone wants it, you can also make the timer async and await it:

export const delay = (ms) => new Promise((res) => setTimeout(res, ms));

Usage:

// do something
await delay(500); // wait 0.5 seconds
// do something else
import React, {Component} from 'react';
import {StyleSheet, View, Text} from 'react-native';


class App extends Component {
componentDidMount() {
setTimeout(() => {
this.props.navigation.replace('LoginScreen');
}, 2000);
}


render() {
return (
<View style={styles.MainView}>
<Text>React Native</Text>
</View>
);
}
}


const styles = StyleSheet.create({
MainView: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
});


export default App;