ReactJS:setTimeout()不起作用?


100

请记住以下代码:

var Component = React.createClass({

    getInitialState: function () {
        return {position: 0};    
    },

    componentDidMount: function () {
        setTimeout(this.setState({position: 1}), 3000);
    },

    render: function () {
         return (
            <div className="component">
                {this.state.position}
            </div>
         ); 
    }

});

ReactDOM.render(
    <Component />,
    document.getElementById('main')
);

难道不应该在3秒后改变状态吗?它立即改变。

我的主要目标是每3秒更改一次状态(使用setInterval()),但是由于它不起作用,因此我尝试了setTimeout(),该方法也不起作用。上面有灯吗?谢谢!


2
如果有foo(bar())bar先执行和其返回值传递给foo
菲利克斯·克林

@FelixKling似乎正确,但不合适。由于foo()此处恰好bar在所需的超时后执行。还是我完全错了,它立即执行,只在期望的时间之后返回值?
jbarradas

3
“由于foo()正是在所需的超时后执行bar。” 是的,这就是为什么您必须传递bar,而不是调用它并传递其返回值的原因。您是否期望行为foo(bar())会改变,取决于foo正在做什么?那真的很奇怪。
菲利克斯·克林

Answers:


241

setTimeout(
    function() {
        this.setState({ position: 1 });
    }
    .bind(this),
    3000
);

否则,您会将的结果传递setStatesetTimeout

您还可以使用ES6箭头功能来避免使用this关键字:

setTimeout(
  () => this.setState({ position: 1 }), 
  3000
);

1
是的,这很有用,而且有效。但是function()不是函数吗?那么为什么我们需要绑定它呢?我已经尝试过了,真的很需要它,我只是想知道为什么。感谢您的帮助:)
jbarradas

我不明白为什么您要说它将结果传递给setTimeout,这怎么办?在这种情况下会发生什么?
PositiveGuy

16
对于那些更喜欢使用ES6箭头功能的用户: setTimeout(() => {this.setState({ position: 1 })}, 3000)@PositiveGuy不知道自从发布此问题以来是否自行研究过此内容,但如果您没有这样做,则:Daniel的原始示例需要.bind(this)this上下文限制为setState-否则,this将自动指其中它被调用(在这种情况下,匿名的上下文function被传递到setTimeout)。但是,ES6箭头函数在词法上是作用域内的 -它们仅限this于调用​​它们的上下文。
Zac Collier

1
不起作用... setTimeout(()=> {if(!this.props.logoIsLoading &&!this.props.isLoading){console.log('我们会发生吗?'); this.setState({。 。它在类语法糖类组织的上下文中扩展了组件{console.log从不获取console.log('我们会发生吗?' 记录之前和之后的所有内容。
juslintek

@juslintek定义不起作用。请根据需要提出一个新问题。
丹尼尔·A·怀特

150
setTimeout(() => {
  this.setState({ position: 1 });
}, 3000);

由于ES6箭头功能不会更改的上下文,因此上述方法也将起作用this


3
ES6语法应该是React最佳实践的公认答案。两者都可以使用,但这更加优雅和处理this
mccambridge

24

每当我们创建超时时,如果尚未触发,则应在componentWillUnmount上清除它。

      let myVar;
         const Component = React.createClass({

            getInitialState: function () {
                return {position: 0};    
            },

            componentDidMount: function () {
                 myVar = setTimeout(()=> this.setState({position: 1}), 3000)
            },

            componentWillUnmount: () => {
              clearTimeout(myVar);
             };
            render: function () {
                 return (
                    <div className="component">
                        {this.state.position}
                    </div>
                 ); 
            }

        });

ReactDOM.render(
    <Component />,
    document.getElementById('main')
);

11

我知道这有点旧了,但是要注意,React建议重新安装组件,以清除安装间隔:https ://reactjs.org/docs/state-and-lifecycle.html

所以我想在这个讨论中添加这个答案:

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }
  componentWillUnmount() {
    clearInterval(this.timerID);
  }

8

setState由于括号而被立即调用!将其包装在一个匿名函数中,然后调用它:

setTimeout(function() {
    this.setState({position: 1})
}.bind(this), 3000);

6

你没有告诉谁叫setTimeout

在这里,如何调用超时而无需调用其他函数。

1.您可以执行此操作而无需执行其他功能。

setTimeout(this.setState.bind(this, {position:1}), 3000);

使用function.prototype.bind()

setTimeout获取函数的位置并将其保留在上下文中。

2.即使编写更少的代码也可以做到这一点。

setTimeout(this.setState, 3000, {position:1});

可能在某些时候使用了相同的绑定方法

setTimeout仅占据函数的位置,并且函数已经具有上下文?无论如何,它有效!

注意:这些可与您在js中使用的任何功能一起使用。


5

您的代码作用域(this将是您的window对象,而不是您的react组件,因此这setTimeout(this.setState({position: 1}), 3000)将导致崩溃。

那是来自javascript而不是React,它是js闭包


因此,为了绑定您当前的反应组件范围,请执行以下操作:

setTimeout(function(){this.setState({position: 1})}.bind(this), 3000);

或者,如果您的浏览器支持es6,或者您的projs支持将es6编译为es5,请尝试使用箭头功能,因为箭头功能可解决“此”问题:

setTimeout(()=>this.setState({position: 1}), 3000);

3

有3种方法可以访问'setTimeout'函数内部的范围

第一,

const self = this
setTimeout(function() {
  self.setState({position:1})
}, 3000)

其次是使用ES6箭头功能,导致箭头功能本身没有作用域(此)

setTimeout(()=> {
   this.setState({position:1})
}, 3000)

第三个是在函数内部绑定范围

setTimeout(function(){
   this.setState({position:1})
}.bind(this), 3000)

1

您做了语法声明错误,请使用正确的setTimeout声明

message:() => { 
  setTimeout(() => {this.setState({opened:false})},3000); 
  return 'Thanks for your time, have a nice day 😊! 
}
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.