【问题标题】:setTimeout in React NativeReact Native 中的 setTimeout
【发布时间】:2016-04-02 22:34:10
【问题描述】:

我正在尝试为在 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/…
  • 出于某种原因,我只能看到setTimeoutrender 方法中使用,这将为每个渲染创建一个新的超时......在render 中创建副作用是一种反模式。其余的已经回答了

标签: javascript ios settimeout react-native


【解决方案1】:

经典的 javascript 错误。

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

setTimeout 运行this.setState 时,this 不再是CowtanApp,而是window。如果你用=&gt;符号定义函数,es6会自动绑定this

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

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

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

如果不起作用,请使用bind

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

【讨论】:

  • 救了我,谢谢!我是 js 新手,这可能很愚蠢,但有没有办法用“传统”函数(){}方式来做到这一点?
  • 请注意,通常你不会在render 方法中调用setTimeout。这是一种 React 反模式,用于在渲染中修改状态或产生副作用。还会为每个渲染通道创建一个新计时器
【解决方案2】:

为 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 函数进行启动说明。
  • 由于范围问题,它无法正常工作。在您的原始代码中,您有 setTineout(function() { 当在该块中时,它指的是您的组件以外的东西。这里答案的替代方法是将您的 setTimeout 调用简单地更改为“ES2015 Fat Arrow Sytax”,例如: setTimeout(() => this.setState((...)
【解决方案3】:

更改此代码:

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

到以下:

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

【讨论】:

    【解决方案4】:

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

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

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

    【讨论】:

      【解决方案5】:
      const getData = () => {
      // some functionality
      }
      
      const that = this;
         setTimeout(() => {
         // write your functions    
         that.getData()
      },6000);
      

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

      【讨论】:

        【解决方案6】:

        如果有人想要它,你也可以让计时器异步并等待它:

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

        用法:

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

        【讨论】:

          【解决方案7】:

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

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

          【讨论】:

            【解决方案8】:

            永远不要在 render 方法中调用 setState

            您应该永远不要render 方法中调用 setState为什么? 调用setState 最终会再次触发render 方法。这意味着您在一个永远不会结束的循环中调用 setState(在您的 render 块中提到)。正确的做法是在 React 中使用 componentDidMount 钩子,如下所示:

            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 使用三元运算符以获得更简洁、更短且易读的代码。

            【讨论】:

              【解决方案9】:

              简单的setTimeout(()=&gt;{this.setState({loaded: true})}, 1000); 用这个来超时。

              【讨论】:

                【解决方案10】:

                当手机/模拟器的时间与服务器的时间不同时(react-native 打包程序正在运行),这似乎是一个问题。就我而言,手机和电脑的时间相差 1 分钟。同步它们后(没有做任何花哨的事情,手机设置为手动时间,我只是将其设置为使用网络(sim)提供的时间),一切正常。 Thisgithub issue 帮我找到了问题。

                【讨论】:

                  【解决方案11】:
                  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;
                  

                  【讨论】:

                    【解决方案12】:

                    同上,可能对某些人有所帮助。

                    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);
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 2023-04-05
                      • 2018-12-12
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2021-09-20
                      • 1970-01-01
                      相关资源
                      最近更新 更多