web-dev-qa-db-ja.com

ReactアプリのsetInterval

私はまだReactでかなり新しいですが、私はゆっくりと研ぎ澄ましていて、私は私が行き詰まっている何かに遭遇しました。

私はReactで "timer"コンポーネントを構築しようとしています、そして正直に言うと、私がこれを正しく(または効率的に)行っているかどうかはわかりません。以下のコードでは、状態をオブジェクト{ currentCount: 10 }を返すように設定し、componentDidMountcomponentWillUnmount、およびrenderを使用していますが、状態を10から9までの「カウントダウン」にしかできません。

二部構成の質問:私は何が間違っているのですか?また、(componentDidMountおよびcomponentWillUnmountを使用するのではなく)setTimeoutを使用するより効率的な方法はありますか?

前もって感謝します。

import React from 'react';

var Clock = React.createClass({

  getInitialState: function() {
    return { currentCount: 10 };
  },

  componentDidMount: function() {
    this.countdown = setInterval(this.timer, 1000);
  },

  componentWillUnmount: function() {
    clearInterval(this.countdown);
  },

  timer: function() {
    this.setState({ currentCount: 10 });
  },

  render: function() {
    var displayCount = this.state.currentCount--;
    return (
      <section>
        {displayCount}
      </section>
    );
  }

});

module.exports = Clock;
76
Jose

あなたのコードには4つの問題があります。

  • あなたのタイマー方法では、常に10にあなたの現在のカウントを設定しています
  • Renderメソッドで状態を更新しようとしています
  • 実際に状態を変更するためにsetStateメソッドを使用するのではありません
  • IntervalIdを状態に保存していません

それを修正してみましょう。

componentDidMount: function() {
   var intervalId = setInterval(this.timer, 1000);
   // store intervalId in the state so it can be accessed later:
   this.setState({intervalId: intervalId});
},

componentWillUnmount: function() {
   // use intervalId from the state to clear the interval
   clearInterval(this.state.intervalId);
},

timer: function() {
   // setState method is used to update the state
   this.setState({ currentCount: this.state.currentCount -1 });
},

render: function() {
    // You do not need to decrease the value here
    return (
      <section>
       {this.state.currentCount}
      </section>
    );
}

これにより、タイマーが10から-Nに減少します。あなたが0に減少するタイマーが欲しいなら、あなたはわずかに修正されたバージョンを使うことができます:

timer: function() {
   var newCount = this.state.currentCount - 1;
   if(newCount >= 0) { 
       this.setState({ currentCount: newCount });
   } else {
       clearInterval(this.state.intervalId);
   }
},
132
dotnetom

class Clock extends Componentを使用して10秒カウントダウンを更新しました

import React, { Component } from 'react';

class Clock extends Component {
  constructor(props){
    super(props);
    this.state = {currentCount: 10}
  }
  timer() {
    this.setState({
      currentCount: this.state.currentCount - 1
    })
    if(this.state.currentCount < 1) { 
      clearInterval(this.intervalId);
    }
  }
  componentDidMount() {
    this.intervalId = setInterval(this.timer.bind(this), 1000);
  }
  componentWillUnmount(){
    clearInterval(this.intervalId);
  }
  render() {
    return(
      <div>{this.state.currentCount}</div>
    );
  }
}

module.exports = Clock;
27
Greg Herbowicz

Hooksを使用して10秒のカウントダウンを更新しました(クラスを作成せずにstateやその他のReact機能を使用できるようにする新しい機能提案。現在はReact v16.7.0-alphaにあります)。

import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';

const Clock = () => {
    const [currentCount, setCount] = useState(10);
    const timer = () => setCount(currentCount - 1);

    useEffect(
        () => {
            if (currentCount <= 0) {
                return;
            }
            const id = setInterval(timer, 1000);
            return () => clearInterval(id);
        },
        [currentCount]
    );

    return <div>{currentCount}</div>;
};

const App = () => <Clock />;

ReactDOM.render(<App />, document.getElementById('root'));
9
Greg Herbowicz

ありがとう@ dotnetom、@ greg-herbowicz

「this.state is undefined」が返される場合-タイマー機能をバインドします:

constructor(props){
    super(props);
    this.state = {currentCount: 10}
    this.timer = this.timer.bind(this)
}
0
tulsluper