2016-08-30 13 views
0

10秒間カウントするReactコンポーネントにカウントダウンタイマーがあります。 10秒以内にコンポーネントがバックエンドデータを受信すると、タイマーは停止します。そうでない場合は、データが受信されるまで、ページがリフレッシュされ、再びカウントダウンされるなど、0にカウントダウンされます。私のコードは以下の通りです:setIntervalタイマーがReactJSのrender()で正しく機能していない

constructor() { 
    ... 
    this.counter = 10; 
    ... 
} 

render() { 
    const interval = setInterval(() => { 
     const result = this.state.data; 
     if (result) { 
      this.setState({ 
       resultsReceived: true 
      }); 
      clearInterval(interval); 
     } else { 
      this.setState({ 
       resultsReceived: false 
      }); 

      this.counter = this.counter - 1; 
      if (this.counter === 0) { 
       window.location.reload(); 
      } 
     } 
    }, 1000); 

問題は、タイマーが毎秒減少するようには見えないということです。代わりに、動作が不安定です - 10から多分7まで、それは非常に高速です、そして、それはハングアップするか、0の後、すなわち負になるかもしれません。ページが正常に読み込まれています。このコードは間違っているのですか、それともReactの状態に関連する問題ですか?どんな助けも素晴らしいだろう!

UPDATE:

私はこれにコードを変更:

constructor() { 
    this.state = { 
     ... 
     interval: '', 
     counter: 10 
    }; 
} 

componentWillMount() { 
    $.ajax({ 
     url: this.props.api, 
     datatype: 'json', 
     cache: false, 
     success: (data) => { 
      this.setState({ data }); 
     } 
    }); 
    const interval = setInterval(() => { 
     const results = this.state.data; 
     if (results) { 
      this.setState({ 
       resultsReceived: true 
      }); 
      clearInterval(this.state.interval); 
     } else { 
      this.setState({ 
       resultsReceived: false 
      }); 
      let counter; 
      counter = this.state.counter - 1; 
      this.setState({ counter }); 
      if (this.state.counter === 0) { 
       window.location.reload(); 
      } 
     } 
    }, 1000); 
    this.setState({ interval }); 
} 

componentWillUnmount() { 
    clearInterval(this.state.interval); 
} 

タイマーが正常に初めての作品という点でそれが以前よりも優れている - それは10ごとに1〜0秒から行きます。ただし、10秒経過してもデータがロードされておらず、タイマーが再び10から開始すると、データが最後にロードされるまで9に達してから停止します。ページも非常に遅くなります。

+0

https://facebook.github.io/react/docs/component-specs.htmlあなたが探していることをお勧めします* componentWillMount *と* componentWillUnmount * –

+0

あなたは何度も新しいインターバルを開始していませんか?レンダリング()関数にコードを入れてタイマーを使う?私はreactjsに精通していませんが、通常render()は1秒間に複数回呼び出されます。 –

+0

@AntonBanchevおそらく。 JesúsQuintanaが言ったように、私はcomponentWillMountとcomponentWillUnmountでそれらを使用しようとしています – user3033194

答えて

1

なぜこのようなことが起こっているのか分かりませんが、あなたのコードはやや奇妙です。

  1. まず、stateの間隔を維持することは非常に奇妙です。代わりに、コンポーネントインスタンスに保持して、簡単にクリアすることができます。

  2. データを設定して間隔を置いてチェックしないでください。 apiリクエストが完了し、データを状態に設定すると、間隔を解放することができます。

  3. コンポーネントが破棄されるまでの間隔を常にクリアします。

これは私が示唆できるものです。

constructor() { 
    ... 
    this.interval = null 
    this.state = { counter: 10 } 
    ... 
} 

componentWillMount() { 
    $.ajax({ 
    url: this.props.api, 
    datatype: 'json', 
    cache: false, 
    success: (data) => { 
     this.setState({ data }) 
     clearInterval(this.interval); 
    }, 
    }); 

    this.interval = setInterval(() => { 
    if (counter <= 0) { 
     clearInterval(this.interval); 
     location.reload(); 
     return; 
    } 

    this.setState({ 
     counter: this.state.counter - 1, 
    }); 
    }, 1000); 
} 

componentWillUnmount() { 
    clearInterval(this.interval) 
} 

実際には、間隔を使用し、あなたのstate.counterが経過したどのように多くの秒チェックするためにのみ存在する場合、それは非常に良いだろうsetTimeoutをしていない場合。

constructor() { 
    ... 
    this.timeout = null 
    ... 
} 

componentWillMount() { 
    $.ajax({ 
    url: this.props.api, 
    datatype: 'json', 
    cache: false, 
    success: (data) => { 
     this.setState({ data }) 
     clearTimeout(this.timeout); 
    } 
    }); 

    this.timeout = setTimeout(() => { 
    clearTimeout(this.timeout); 
    location.reload(); 
    }, 1000 * 10); 
} 

componentWillUnmount() { 
    clearTimeout(this.timeout) 
} 

setIntervalは高価です。この種の作業には使用しないでください。

+0

ありがとう!それはうまくいった。実際には、毎秒減少するカウンタ値を表示する必要があるため、最初のソリューションを使用しました。しかし私はあなたの2番目の解決策も理解しました。私は前にReactでsetIntervalを使用していないので、あなたのソリューションから学んだ – user3033194

関連する問題