我有如下组件:
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
渲染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/')
正在抛出错误。
关于Stack Overflow中其他类似问题的进一步研究,我还发现这实际上是在render方法下设置父状态,这是不允许的。
但现在我无法弄清楚如何才能达到我想要的条件。
答案 0 :(得分:1)
组件props
不应该自行变异。我认为在这种情况下有两种解决方案。
this.props.history
复制到state
,并通过调用history
变更setState
。将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
}
...
}
...