web-dev-qa-db-ja.com

componentDidMount()のsetTimeout()が機能しない

以下のように、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>
    );
  }
}

ただし、実行は1回だけです。 falseからtrueに変わり、その後は何も変わりません。何が欠けていますか?

4
sruthi sripathi

componentDidMount()は、コンポーネントがマウントされたときに1回だけ実行され、スケジュールは1回だけです。定期的にスケジュールするには、setInterval()を使用する必要があります。

また、現在の状態に基づいて状態を更新するときは、setState()のコールバックを使用する必要があります。これは、reactがsetState()への複数の呼び出しをバッチ処理する可能性があるため、以前の状態を取ります。

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 ...
}
11
trixn

setTimeoutは一度だけ実行されます。探しているのはsetIntervalです。

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

WindowOrWorkerGlobalScope mixin(およびwindow.setTimeoutの後継)のsetTimeout()メソッドは、関数または指定されたコードを一度に実行するタイマーを設定しますタイマーが切れます。

と比べて

WindowOrWorkerGlobalScopeミックスインのsetInterval()メソッドrepeatedlyは、関数を呼び出すか、コードスニペットを実行します。各呼び出しの間に一定の時間遅延があります。

4

コメントで述べたように、setIntervalを使用する必要があります。関数setTimeoutは1回呼び出されます。コンポーネントがアンマウントするときは、必ずsetIntervalをクリアしてください。 https://reactjs.org/docs/react-component.html#componentwillunmount

コード。

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>
    );
  }
}
2
Damien