我正在尝试使用setState()方法重置容器中的React状态变量(默认值)。但是得到以下错误
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`.
最后:超出了最大调用堆栈大小。
我的代码如下:
resetMsg=()=> {
const company = this.state.company;
company.id = 0;
company.messages = [];
this.setState({company: company});
}
当Redux状态的变量为真时,我调用resetMsg()。
我调用resetMsg的代码(resetMessages的值最初为false,我需要重置React-state,当它为true时):
render() {
if(this.props.resetMessages){
this.resetMsg();
}
答案 0 :(得分:11)
您可能需要查看componentWillReceiveProps(nextProps)
函数。根据官方文档:
在挂载的组件接收新道具之前调用
componentWillReceiveProps()
。如果您需要更新状态以响应prop更改(例如,重置它),您可以比较this.props和nextProps并使用此方法中的this.setState()执行状态转换。
这是您要进行重置的地方。如下所示:
componentWillReceiveProps(nextProps) {
if(nextProps.resetMessages) {
const company = Object.assign({}, this.state.company);
company.id = 0;
company.messages = [];
this.setState({company: company});
}
}
每次将道具发送到组件时,上面的代码段都会运行。它首先检查resetMessages
道具是否真实。如果是,则会创建company
状态的临时副本,更改id
和messages
属性值,然后使用新值更新company
。
我想强调您对代码所遇到的问题:
在setState()
内拨打render()
是禁忌。
一般情况下,只要您拨打setState()
,render()
将在之后运行。在render()
内部执行此操作将导致再次调用该函数,并再次调用...
直接改变状态和/或道具。
此行const company = this.state.company;
不会创建状态变量的副本。它只存储引用。所以一旦你这样做,然后做company.id = ...
你基本上做this.state.company.id = ...
,这在React中是反模式的。我们只通过setState()
更改状态。
要创建副本,请对对象使用Object.assign({}, this.state.yourObject)
,对数组使用this.state.yourArray.slice()
。
答案 1 :(得分:5)
componentWillReceiveProps现在(自18年6月以来)已被弃用
您应该使用react docs中提供的替代方法之一。
在您的情况下,我认为使用getDerivedStateFromProps的“不那么推荐”替代版本1是合理的,因为您只是在重新计算状态变量:
getDerivedStateFromProps(props, state) {
if(props.resetMessages) {
const company = Object.assign({}, state.company);
company.id = 0;
company.messages = [];
return {
company: company
}
}
答案 2 :(得分:0)
使用componentWillReceiveProps
检查道具
export class SomeClass {
resetMsg = () => {
let newCompany = {} // don't reuse state.company, create new object!
newCompany = 0;
newCompany.messages = [];
this.setState({company: newCompany});
}
componentWillReceiveProps = (nextProps) => {
if (nextProps.resetMessages !== this.props.resetMessages) { // check if props changed
if (nextProps.resetMessages === true) { // check if prop has correct value
this.resetMsg()
}
}
}
render () {
return () // Your super cool app code
}
}