2017-08-21 68 views
0

我有分量如下:的setState(...):現有的狀態轉換過程中無法更新(如內`render`或其他部件的構造)

const VIEW_PROFILE = 'profile' 
const VIEW_SAA = 'saa' 
const VIEW_DOCUMENTS = 'documents' 
const VIEW_FINANCIERS = 'viewFinancierInfo' 

class ViewFinancier extends Component { 
    constructor(props) { 
    super(props) 
    this.state = { 
     selectedNavigation: VIEW_PROFILE, 
     financierId: this.props.location.state.financierDetails.financierId, 
     defaultLoading: false 
    } 

    this.handleChangeNav = this.handleChangeNav.bind(this) 
    this.handleCancelButton = this.handleCancelButton.bind(this) 
    } 

    componentWillMount(props) { 
    this.props.loadFinancierProfile(this.props.location.state.financierDetails.financierId) 
    } 

    componentWillReceiveProps(newProps) { 
    this.setState({ 
     defaultLoading: true, 
     viewfinancierprofiledata: newProps.viewfinancierprofiledata 
    }) 
    } 

    handleChangeNav(e) { 
    var selectedNavigation = e.target.attributes.getNamedItem('value').value 
    this.setState({ 
     selectedNavigation: selectedNavigation 
    }) 
    } 

    handleCancelButton(changingState) { 
    this.setState({ 
     selectedNavigation: changingState 
    }) 
    } 

    render() { 
    if (this.state.defaultLoading === false) { 
     return (
     <div className="tabledataloading tabletext"> 
      Please wait while the data is loading <img alt="Loading..." src={loadingimg} /> 
     </div> 
    ) 
    } else if (this.state.selectedNavigation === VIEW_FINANCIERS) { 
     this.props.history.push('/financier/') 
     return null 
    } else { 
     return (
     <div id="lesse-info-component-wrapper" className="melody-common-container"> 
      <div id="header-wrapper"> 
      <h1 className="melody-common-module-title">VIEW FINANCIER INFO</h1> 
      </div> 
      <div id="navigation-wrapper"> 
      <ul id="add-financier-info-nav" className="topnavpad"> 
       <li 
       value={VIEW_PROFILE} 
       onClick={this.handleChangeNav} 
       className={'add-financier-info-nav-item ' + (this.state.selectedNavigation === VIEW_PROFILE ? 'active' : '')}> 
       PROFILE 
       </li> 
       <li 
       value={VIEW_SAA} 
       onClick={this.handleChangeNav} 
       className={'add-financier-info-nav-item ' + (this.state.selectedNavigation === VIEW_SAA ? 'active' : '')}> 
       SAA 
       </li> 
       <li 
       value={VIEW_DOCUMENTS} 
       onClick={this.handleChangeNav} 
       className={'add-financier-info-nav-item ' + (this.state.selectedNavigation === VIEW_DOCUMENTS ? 'active' : '')}> 
       DOCUMENTS 
       </li> 
      </ul> 
      </div> 
      {this.state.selectedNavigation === VIEW_PROFILE 
      ? <ViewFinancierProfile financierId={this.props.financierId} onCancelHandler={this.handleCancelButton} /> 
      : null} 
      {this.state.selectedNavigation === VIEW_SAA 
      ? <ViewFinancierSAA financierId={this.props.financierId} onCancelHandler={this.handleCancelButton} /> 
      : null} 
      {this.state.selectedNavigation === VIEW_DOCUMENTS 
      ? <ViewFinancierDocument financierId={this.props.financierId} onCancelHandler={this.handleCancelButton} /> 
      : null} 
     </div> 
    ) 
    } 
    } 
} 

const mapStateToProps = state => { 
    return { 
    viewfinancierprofiledata: state.viewfinancierprofiledata 
    } 
} 

const mapDispatchToProps = dispatch => { 
    return { 
    loadFinancierProfile: financierId => dispatch(viewFinancierProfileAction.loadFinancierProfile(financierId)) 
    } 
} 

export default connect(mapStateToProps, mapDispatchToProps)(ViewFinancier) 

而且在執行我收到警告:Warning: setState(...): Cannot update during an existing state transition (such as within render or another component's constructor). Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, but can be moved to componentWillMount`

在調查控制檯時,我發現代碼段this.props.history.push('/financier/')正在引發錯誤。

關於在StackOverflow中的其他類似問題的進一步研究,我還發現,這實際上設置父母狀態下渲染方法,這是不允許的。

但現在我無法弄清楚我如何達到我所期望的狀況。

請建議。在此先感謝

回答

1

組件props不應自行突變。我認爲在這種情況下有兩種解決方案。

  1. 複製this.props.historystate,並通過調用setState變異history。把selectedNavigation的檢查放在render之外。例如(只是我的主意,請修改它基於應用程序邏輯的):

class ViewFinancier extends Component { 
 
    constructor(props) { 
 
    super(props) 
 
    this.state = { 
 
     ... 
 
     history = props.history, 
 
     ... 
 
    } 
 
    ... 
 
    } 
 

 
    componentWillReceiveProps(newProps) { 
 
    this.setState({ 
 
     history: newProps.history, 
 
     ... 
 
    }) 
 
    } 
 
    
 
    handleChangeNav(e) { 
 
    var selectedNavigation = e.target.attributes.getNamedItem('value').value; 
 
    
 
    this.setState({ 
 
     selectedNavigation: selectedNavigation  
 
    }) 
 
    
 
    this.historyCheck(selectedNavigation); 
 
    } 
 

 
    handleCancelButton(changingState) { 
 
    this.setState({ 
 
     selectedNavigation: changingState 
 
    }); 
 
    
 
    this.historyCheck(changingState); 
 
    } 
 
    
 
    historyCheck(nav) { 
 
    if (nav === VIEW_FINANCIERS) { 
 
     history.push('/financier/'); 
 
    }; 
 
    
 
    this.setState(history: history); 
 
    } 
 

 
    render() {  
 
    ... 
 
    } else if (this.state.selectedNavigation === VIEW_FINANCIERS) { 
 
     return null 
 
    } 
 
    ... 
 
    } 
 
}

  • 如果this.props.history使用由父組件也。然後,您可以傳遞一個函數,以便從父組件更新history並將此函數傳遞給您當前的(子)組件。
  • class ParentFinancier extends Component { 
     
        pushHistory => (val) { 
     
        let {history} = this.state; 
     
        this.setState(history: history.push('/financier/')); 
     
        } 
     
        
     
        render() { 
     
        ... 
     
        <ViewFinancier pushHistory={this.pushHistory} ... /> 
     
        } 
     
        ... 
     
    } 
     
    
     
    
     
    
     
    class ViewFinancier extends Component { 
     
        ... 
     
        } else if (this.state.selectedNavigation === VIEW_FINANCIERS) { 
     
        this.props.pushHistory('/financier/') 
     
        return null 
     
        } 
     
        ... 
     
    } 
     
    
     
    ...

    +0

    對於點#1,我怎麼能發生變異使用的setState在渲染方法的歷史,它會再次成爲同樣的情況,對不對? –

    +1

    @OMTheEternity:回答更新的更多細節。 –

    +0

    我按照我的代碼流使用了第一種方法...我對此很滿意。謝謝您的幫助 –

    相關問題