React Native中的setTimeout


75

我正在尝试为React Native内置的iOS应用加载启动画面。我试图通过类状态,然后通过setTimeout函数来完成此操作,如下所示:

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',
          }}/>
      );
    }
  }
}

加载页面会工作一秒钟,然后我猜想setTimeout尝试将状态更改为true时,我的程序崩溃了:“未定义不是对象(正在评估this.setState)”。我已经花了几个小时了,关于如何解决它的任何想法?


检查设备的时间是否与计算机的时间匹配!这发生在我身上,把一个不幸半晌debug stackoverflow.com/questions/51163349/...
马赫迪Bashirpour

Answers:


148

经典的JavaScript错误。

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

setTimeout运行this.setStatethis不再CowtanApp,但window。如果使用=>符号定义函数,则es6将自动绑定this

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

或者,您可以let that = this;在的顶部使用a render,然后将引用切换为使用局部变量。

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

如果不起作用,请使用bind

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

2
救了我,谢谢!我是js新手,这可能很愚蠢,但是有没有办法使用“传统” function(){}方法呢?
t-gao

15

为settimeout编写一个新函数。请尝试一下。

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',
      }}/>
  );
}
}
}

好的,这有效-谢谢!您能否解释一下为什么它无法在渲染中工作?
菲尔

我认为您根本无法在render方法中编写任何指令。您可以使用componentWillMount或componentDidMount函数获取启动说明。
Phyo 2015年

6
由于范围问题,它不起作用。在您的原始代码中,您有setTineout(function(){,它在该代码块中引用的是组件之外的其他东西。在这里,答案的另一种选择是将setTimeout调用更改为“ ES2015 Fat Arrow Sytax”,例如:setTimeout(()=> this.setState((...)
rmevans9

7

更改此代码:

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

到以下内容:

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

7

在ReactNative .53上,以下对我有用:

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

setTimeout是ReactNative库函数。
“ this.timeoutCheck”是我的变量,用于保存超时对象。
“ this.setTimePassed”是我在超时时调用的函数。


4

您可以this通过.bind(this)直接添加到函数定义的末尾来绑定到函数。您将代码块重写为:

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

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

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

6000毫秒后即可触发简单的Settimout函数


2

如果有人需要它,您还可以使计时器异步并等待它:

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

用法:

// do something
await delay(500); // wait 0.5 seconds
// do something else


1

当电话/仿真器的时间与服务器(正在运行react-native打包程序的服务器)的时间不同时,似乎会出现问题。以我为例,手机和计算机之间的时间相差1分钟。同步它们之后(没有做任何花哨的事情,电话被设置为手动时间,而我只是将其设置为使用提供的网络(sim)时间),一切正常。这个github问题帮助我找到了问题。


1

永不调用setState内部render方法

永远不应该setStaterender方法内部调用。为什么?setState最终调用将render再次触发该方法。这意味着您将在永render无休止的循环中调用setState(在您的块中提到)。正确的方法是componentDidMount在React中使用钩子,如下所示:

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使用三元运算符可以使代码更简洁,简短和可读。


0

与上述相同,可能会对某些人有所帮助。

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);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.