2017-08-14 8 views
0

8秒間ロードしたときに取り消すロードコンポーネントがあります。このコードは動作しますが、それは私には気分が悪く、これを行うためのよりよい方法があるのだろうかと思います。componentWillUnmountでclearTimeoutを改善する方法

this.mountedを設定せずに、私はエラーを取得する:

Warning: Can only update a mounted or mounting component. This usually means you called setState, replaceState, or forceUpdate on an unmounted component. This is a no-op. Please check the code for the Loading component.

これは私はそれがthis.seStateと続くので、タイマーが取り消さなっていないことを考えさせます。 componentWillUnmountclearTimeoutを設定するとどうなりますか?これを処理するには、グローバルthis.mountedを使用するよりも良い方法はありますか?

class Loading extends Component { 
    state = { 
    error: false, 
    }; 

    componentDidMount =() => { 
    this.mounted = true; 
    this.timer(); 
    }; 

    componentWillUnmount =() => { 
    this.mounted = false; 
    clearTimeout(this.timer); 
    }; 

    timer =() => 
    setTimeout(() => { 
     (this.mounted && this.setState({ error: true })) || null; 
    }, 8000); 

    render() { 
    const { showHeader = false } = this.props; 
    const { error } = this.state; 
    return (
     <View style={backgroundStyle}> 
     {showHeader && <HeaderShell />} 
     {!error && 
      <View style={loadingHeight}> 
      <PlatformSpinner size="large" /> 
      </View>} 
     {error && <Error code="service" />} 
     </View> 
    ); 
    } 
} 

Loading.propTypes = { 
    showHeader: PropTypes.bool, 
}; 

Loading.defaultProps = { 
    showHeader: false, 
}; 

export default Loading; 
+5

は、あなたは値を保存する必要がありますどこかで 'setTimeout()'から返され、 'clearTimeout()'に渡されます。その関数参照を渡していますが、これはうまくいきません。 @Pointyが指摘するように – Pointy

+3

には、setTimeoutから返された値を保存する必要があります。これは、 'componentWillUnmount'ライフサイクルメソッドを使用してこの操作を行うのが好ましい場所です。 –

+0

setTimeoutによって返される値は、8秒に達しない限り、やりたくない状態を設定しています。 – Turnipdabeets

答えて

3

This make me think that the timer is not getting canceled

先のとがったが、それはない、言ったように。 ファンクションthis.timer)をclearTimeoutに渡しています。 setTimeout戻り値(タイマーのハンドル)を渡す必要があります。そのハンドルを使用して取り消すことができます。

このような単純な構成要素では、私はtimer機能の必要性を認識していません。

class Loading extends Component { 
    state = { 
    error: false, 
    }; 

    componentDidMount =() => {    // *** 
    // Remember the timer handle    // *** 
    this.timerHandle = setTimeout(() => { // *** 
     this.setState({ error: true });  // *** 
     this.timerHandle = 0;     // *** 
    }, 8000);        // *** 
    };           // *** 
              // *** 
    componentWillUnmount =() => {    // *** 
    // Is our timer running?     // *** 
    if (this.timerHandle) {     // *** 
     // Yes, clear it      // *** 
     clearTimeout(this.timerHandle);  // *** 
     this.timerHandle = 0;    // *** 
    }          // *** 
    };           // *** 

    render() { 
    const { showHeader = false } = this.props; 
    const { error } = this.state; 
    return (
     <View style={backgroundStyle}> 
     {showHeader && <HeaderShell />} 
     {!error && 
      <View style={loadingHeight}> 
      <PlatformSpinner size="large" /> 
      </View>} 
     {error && <Error code="service" />} 
     </View> 
    ); 
    } 
} 

Loading.propTypes = { 
    showHeader: PropTypes.bool, 
}; 

Loading.defaultProps = { 
    showHeader: false, 
}; 

export default Loading; 

でも示されるよりも多くのロジック、または単に個人的な好み、はい、別々の機能が良好であるかどう:私はちょうどCDMでタイマーを設定したい

class Loading extends Component { 
    state = { 
    error: false, 
    }; 

    componentDidMount =() => { 
    this.setTimer(); 
    }; 

    componentWillUnmount =() => { 
    this.clearTimer(); 
    }; 

    setTimer =() => { 
    if (this.timerHandle) { 
     // Exception? 
     return; 
    } 
    // Remember the timer handle 
    this.timerHandle = setTimeout(() => { 
     this.setState({ error: true }); 
     this.timerHandle = 0; 
    }, 8000); 
    }; 

    clearTimer =() => { 
    // Is our timer running? 
    if (this.timerHandle) { 
     // Yes, clear it 
     clearTimeout(this.timerHandle); 
     this.timerHandle = 0; 
    } 
    }; 

    render() { 
    const { showHeader = false } = this.props; 
    const { error } = this.state; 
    return (
     <View style={backgroundStyle}> 
     {showHeader && <HeaderShell />} 
     {!error && 
      <View style={loadingHeight}> 
      <PlatformSpinner size="large" /> 
      </View>} 
     {error && <Error code="service" />} 
     </View> 
    ); 
    } 
} 

Loading.propTypes = { 
    showHeader: PropTypes.bool, 
}; 

Loading.defaultProps = { 
    showHeader: false, 
}; 

export default Loading; 
+0

書き取りいただきありがとうございます。 0に設定する理由は何ですか? 'this.timerHandle = 0;' – Turnipdabeets

+0

@Turnipdabeets:私はいつもタイマーハンドルがないことを示すフラグとして( '0'はタイマーハンドルにとって無効な値なので)これをフラグとして使います。便利なフラグも作成します( 'clearTimer'の実装を参照してください)。また、 'setTimer'と' clearTimer'が別々のメソッドである2番目のコードブロックでは、 'setTimer'をチェックインしたいと思うでしょう。 –

0

戻り値をsetTimeout(下記参照)からクリアする必要があります。しかし、をcomponentWillUnmountにするのは正しい方法ですが、私は誰もそれを何か別のやり方で見たことはありません。

componentDidMount =() => { 
    this.mounted = true; 
    this.timeout = this.timer(); 
    }; 

    componentWillUnmount =() => { 
    this.mounted = false; 
    clearTimeout(this.timeout); 
    }; 

    timer =() => 
    setTimeout(() => { 
     (this.mounted && this.setState({ error: true })) || null; 
    }, 8000); 
関連する問題