2016-10-20 13 views
1

次のコンポーネントコードを使用してカウントダウンタイマーを表示しようとしています。React Component警告setState(...):マウントされているコンポーネントまたはマウントされているコンポーネントのみをアップデートできます

:私は私のisMounted状態変数が全体に本当だった場合、私は唯一確認した後の状態を設定したと仮定、しかし

を「警告SETSTATE(...)は、専用でマウントまたはコンポーネント を取り付け更新できます」コンポーネント私のミスはどこですか?

import React, { Component, PropTypes } from 'react' 

export default class CountDownTimerContainer extends Component { 
    static propTypes = { 
    initialTimeRemaining: PropTypes.number.isRequired, 
    interval: PropTypes.number, 
    formatFunc: PropTypes.func, 
    tickCallback: PropTypes.func, 
    completeCallback: PropTypes.func 
    } 

    constructor (props) { 
    super(props) 
    this.state = { 
     timeRemaining: this.props.initialTimeRemaining, 
     timeoutId: null, 
     prevTime: null, 
     isMounted: false 
    } 
    } 

    componentWillMount() { 
    this.setState({isMounted: true}) 
    } 

    componentDidMount() { 
    this.tick() 
    } 

    componentWillReceiveProps (newProps) { 
    if (this.state.timeoutId) { 
     clearTimeout(this.state.timeoutId) 
    } 
    if (this.state.isMounted) { 
     this.setState({prevTime: null, timeRemaining: newProps.initialTimeRemaining}) 
    } 
    } 

    componentDidUpdate() { 
    if ((!this.state.prevTime) && this.state.timeRemaining > 0 && this.state.isMounted) { 
     this.tick().bind(this) 
    } 
    } 

    componentWillUnmount() { 
    this.setState({isMounted: false}) 
    clearTimeout(this.state.timeoutId) 
    } 

    tick() { 
    const currentTime = Date.now() 
    const dt = this.state.prevTime ? (currentTime - this.state.prevTime) : 0 
    const interval = this.props.interval 

    // correct for small variations in actual timeout time 
    const timeRemainingInInterval = (interval - (dt % interval)) 
    let timeout = timeRemainingInInterval 

    if (timeRemainingInInterval < (interval/2.0)) { 
     timeout += interval 
    } 

    const timeRemaining = Math.max(this.state.timeRemaining - dt, 0) 
    const countdownComplete = (this.state.prevTime && timeRemaining <= 0) 

    if (this.state.isMounted) { 
     if (this.state.timeoutId) { 
     clearTimeout(this.state.timeoutId) 
     } 
     this.setState({ 
     timeoutId: countdownComplete ? null : setTimeout(this.tick.bind(this), timeout), 
     prevTime: currentTime, 
     timeRemaining: timeRemaining 
     }) 
    } 

    if (countdownComplete) { 
     if (this.props.completeCallback) { 
     this.props.completeCallback() 
     } 
     return 
    } 

    if (this.props.tickCallback) { 
     this.props.tickCallback(timeRemaining) 
    } 
    } 

    getFormattedTime (milliseconds) { 
    if (this.props.formatFunc) { 
     return this.props.formatFunc(milliseconds) 
    } 

    var totalSeconds = Math.round(milliseconds/1000) 

    var seconds = parseInt(totalSeconds % 60, 10) 
    var minutes = parseInt(totalSeconds/60, 10) % 60 
    var hours = parseInt(totalSeconds/3600, 10) 

    seconds = seconds < 10 ? '0' + seconds : seconds 
    minutes = minutes < 10 ? '0' + minutes : minutes 
    hours = hours < 10 ? '0' + hours : hours 

    return hours + ':' + minutes + ':' + seconds 
    } 

    render() { 
    var timeRemaining = this.state.timeRemaining 
    return (
     <div className='timer'> 
     {this.getFormattedTime(timeRemaining)} 
     </div> 
    ) 
    } 
} 

CountDownTimerContainer.defaultProps = { 
    interval: 1000, 
    formatFunc: null, 
    tickCallback: null, 
    completeCallback: null 
} 

更新:でもComponentWIllMountから

this.setState({isMounted: true}) 

を削除し、私はまだsetStateErrorを得るthis.state({isMounted: true})としてコンストラクタにそれを追加した後。

+0

「setState」の4つの呼び出しが発生しますか? –

+0

これは、私が間違っていることを教えてくれます。 コンポーネントがまだマウントされていないときは、 'componentWillMount'に' setState'を使用します。私は最初にそこに州を設定する必要があるか疑問に思う。 –

+0

これをcomponentDidMountに移動します – abhirathore2006

答えて

1

コンポーネントがマウントされる前に、文字通り.setState()を実行します(componentWillMount())。コンポーネントがまだ存在しないため、これを行うことはできません。むしろ初期状態としてconstructor()に入れてください。

+0

setStateをcomponentDidMount()に移動するとカウンタが動作しなくなり、lintエラーが発生します.componentDidMountでsetStateを使用しないでください – jasan

+0

よ、それを 'constructor()'に 'this.state = {}'として入れてください。それが初期状態です。 –

+0

私はそれをしましたが、私はまだsetStateエラーを取得します。 – jasan

関連する問題

 関連する問題