javascript componentDidMount() 中的 setTimeout() 不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/49276487/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 08:30:48  来源:igfitidea点击:

setTimeout() in componentDidMount() does not work

javascriptreactjssettimeout

提问by sruthi sripathi

I am trying to change the state of a component every 5 seconds as below inside componentDidMount() hook

我试图在 componentDidMount() 钩子内每 5 秒更改一次组件的状态,如下所示

import React, { Component } from 'react';

export default class ToTest extends Component {

  constructor(props) {
    super(props);
    this.state = {
      test: false
    };
  }

  componentDidMount() {
    setTimeout(() => { this.setState({ test: !this.state.test }) }, 5000);
  }

  renderDiv() {
    if(this.state.test) {
      return (<div>test is true</div>)
    }
    else {
      return (<div>test is false</div>)
    }
  }
  render() {
    return (
      <div>{ this.renderDiv() }</div>
    );
  }
}

But it executes only once. It changes from false to true once and then nothing. What am I missing?

但它只执行一次。它从假变为真一次,然后什么也没有。我错过了什么?

回答by trixn

componentDidMount()is only executed once when the component mounts and you only schedule it once. You have to use setInterval()to schedule it periodically.

componentDidMount()仅在组件安装时执行一次,并且您只安排一次。您必须使用setInterval()来定期安排它。

Also when you update the state based on the current state you should use a callback in setState()that takes the previous state as react may batch multiple calls to setState().

此外,当您根据当前状态更新状态时,您应该使用一个回调,setState()该回调采用先前的状态,因为 react 可能会批量调用setState().

And don't forget to cancel the timer in componentWillUnmount():

并且不要忘记取消计时器componentWillUnmount()

import React, { Component } from 'react';

export default class ToTest extends Component {
    state = {
        test: false,
    };

    componentDidMount() {
        this.timer = setInterval(
            () => this.setState(prevState => ({ test: !prevState.test })),
            5000,
        );
    }

    componentWillUnmount() {
        clearInterval(this.timer);
    }

    // other methods ...
}

回答by Martin Schneider

Well setTimeoutwill only execute once, what you are looking for is setInterval:

好吧setTimeout只会执行一次,您正在寻找的是setInterval

https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout

https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout

The setTimeout() method of the WindowOrWorkerGlobalScope mixin (and successor to window.setTimeout) sets a timer which executes a function or specified piece of code once afterthe timer expires.

WindowOrWorkerGlobalScope mixin(和 window.setTimeout 的后继者)的 setTimeout() 方法设置一个计时器,该计时器在计时器到期执行一次函数或指定的代码段。

Compare with

与之比较

The setInterval() method of the WindowOrWorkerGlobalScope mixin repeatedlycalls a function or executes a code snippet, with a fixed time delay between each call.

WindowOrWorkerGlobalScope mixin 的 setInterval() 方法 重复调用函数或执行代码片段,每次调用之间有固定的时间延迟。

回答by Damien

As said in comments, you must use setInterval. the function setTimeoutis called once. Make sure to clear the setInterval when the component unmounts. https://reactjs.org/docs/react-component.html#componentwillunmount

正如评论中所说,您必须使用setInterval. 该函数setTimeout被调用一次。确保在卸载组件时清除 setInterval。https://reactjs.org/docs/react-component.html#componentwillunmount

The code.

代码。

import React, { Component } from 'react';

export default class ToTest extends Component {

  constructor(props) {
    super(props);
    this.state = {
      test: false
    };
  }

  componentDidMount() {
    this.timer = setInterval(() => { this.setState({ test: !this.state.test }) }, 5000);
  }

  componentWillUnmount() {
    clearInterval(this.timer)
  }


  renderDiv() {
    if(this.state.test) {
      return (<div>test is true</div>)
    }
    else {
      return (<div>test is false</div>)
    }
  }
  render() {
    return (
      <div>{ this.renderDiv() }</div>
    );
  }
}