2017-07-20 58 views
0

我收到此錯誤setState(...): Can only update a mounted or mounting component.,但我無法弄清楚如何解決該問題。React JS setState(...):只能更新已安裝或正在安裝的組件

import React, { Component } from 'react'; 

import Loading1 from '../images/loading1.gif'; 

class LoadingSpinner extends Component { 
    constructor(props){ 
    super(props); 

    this.changeState = this.changeState.bind(this); 
    this.timer = this.timer.bind(this); 
    } 

    state = { 
    loadingImg: Loading1, 
    loading: true 
    } 

    timer(){ 
    var self = this; 
    var startTime = new Date().getTime(); 
    var interval = setInterval(function() { 
     if (new Date().getTime() - startTime > 3000) { 
     clearInterval(interval); 
     return; 
     } 
     self.changeState(); 
    }, 2000); 
    } 

    changeState(){ 
    this.setState({ 
     loading: false, 
    }) 
    } 

    render() { 


    const topMargin = { 
     marginTop: "50px" 
    } 


    return (
     <div className="containter" style={topMargin}> 
     <center> 
      {this.state.loading ? <img src={this.state.loadingImg} onLoad= {this.timer()} alt="Loading..." /> : <h2>Unable To Find What You Are Looking  For!</h2> } 
     </center> 
     </div> 
    ); 
    } 
} 

export default LoadingSpinner; 

這是我的代碼導致的問題。

基本上我希望它在設定的時間量之後,會從loading1.gif變成說無法找到你要找的東西。它這樣做,但它會拋出我無法擺脫的錯誤setState(...): Can only update a mounted or mounting component.

這是我如何調用加載微調

<Tab label="Applicant Details" value="GetCasePersonal"> 
    {this.state.GetCasePersonal.length === 0 ? <LoadingSpinner /> : 
    <div> 
     <ViewPersonalDetails Case={this.state.GetCasePersonal} /> 
    </div> 
    } 
</Tab> 
+0

移動你的計時器函數到'componentDidMount'。你從'渲染器'裏面調用它並不能很好地傳達你的意圖。有關生命週期函數的更多信息,請參見:https://facebook.github.io/react/docs/react-component.html – Kyle

+0

@Kyle仍然會這樣做,如果我從那裏執行它 –

回答

3

你不必使用setInterval功能,你可以用setTimeout做到這一點很容易,你應該使用一個陣營的生命週期函數有一個超時而不是調用它形象的onLoad的。

class LoadingSpinner extends React.Component { 
 
    constructor(props){ 
 
    super(props); 
 
    this.timeout = null; 
 
    this.changeState = this.changeState.bind(this); 
 
    } 
 

 
    state = { 
 
    loadingImg: '', 
 
    loading: true 
 
    } 
 

 
    componentDidMount(){ 
 
    
 
    this.timeout = setTimeout(() => { 
 
     console.log('I am changing state'); 
 
     this.changeState(); 
 
    }, 3000); 
 
    } 
 
    componentWillUnmount() { 
 
    clearTimeout(this.timeout); 
 
    } 
 
    changeState(){ 
 
    this.setState({ 
 
     loading: false, 
 
    }) 
 
    } 
 

 
    render() { 
 

 

 
    const topMargin = { 
 
     marginTop: "50px" 
 
    } 
 

 

 
    return (
 
     <div className="containter" style={topMargin}> 
 
     <center> 
 
      {this.state.loading ? <img src={this.state.loadingImg} alt="Loading..." /> : <h2>Unable To Find What You Are Looking  For!</h2> } 
 
     </center> 
 
     </div> 
 
    ); 
 
    } 
 
} 
 

 
ReactDOM.render(<LoadingSpinner/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 
 
<div id="app"></div>

+1

這給了我同樣的錯誤,我試圖擺脫 –

+0

好吧,它不在片段中,問題應該在其他地方出現。我希望你已經擺脫了onLoad和定時器功能 –

+0

它不在片段中,因爲沒有控制檯我說它可以工作,但它會在控制檯中輸入錯誤 –

1

有這個良好的文檔這裏 https://facebook.github.io/react/blog/2015/12/16/ismounted-antipattern.html

當此類問題處理一個很好的做法是尋找在反應的Facebook的文件。

private _isMount = false; 

componentDidMount() { 
    this._isMount = true; 
} 

componentWillUnmount() 
{ 
    this._isMount = false; 
} 

timerJob() 
{ 
    if(this._isMount == false) 
     return; 
    // setState 
} 
+1

雖然這將停止顯示警告,但它並不完全正確使用標誌,而不是React生命週期來處理事件。正確的方法是在'componentDidMount'內啓動定時器,而不是在'onLoad'的'render'方法中啓動定時器。 –

+0

是的,你是正確的,這是更重要的。 – Luke359

+0

@LuísBrito你會怎麼做 –

1

不能調用函數用的setState()到構造函數中,你應該試試這個:

constructor(props){ 
super(props); 
} 

componentDidMount() { 
this.changeState = this.changeState.bind(this); 
this.timer = this.timer.bind(this); 
} 

並檢查LifeCycle of your component

+0

OP不在構造函數中調用它們,而是將它們綁定在一起 –

相關問題