我正在尝试使用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,当它为true时,我需要重置React-state ):
render() {
if(this.props.resetMessages){
this.resetMsg();
}发布于 2018-01-12 20:54:08
您可能需要查看componentWillReceiveProps(nextProps)函数。根据官方文件:
在挂载的组件接收新的属性之前,会调用
componentWillReceiveProps()。如果您需要更新状态以响应适当的更改(例如,重置它),您可以比较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。
我想强调一下您在代码中遇到的问题:
render()内部调用setState()是个禁忌。在一般情况下,只要调用setState(),render()就会随后运行。在render()内部执行此操作将导致该函数一次又一次地被调用,并直接again...
这一行const company = this.state.company;不会创建状态变量的副本。它只存储对它的引用。所以一旦你这样做了,然后再做company.id = ...,你实际上就是在做this.state.company.id = ...,这是React中的反模式。我们只通过setState()来改变状态。
要创建副本,请对对象使用Object.assign({}, this.state.yourObject),对数组使用this.state.yourArray.slice()。
发布于 2018-08-26 16:11:42
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
}
}发布于 2021-12-29 20:50:43
尝试延迟setState()调用,直到渲染完成。您可以使用setTimeout()来实现此目的。例如,而不是:
this.resetMsg()使用
setTimeout(() => this.resetMsg())这将把resetMsg()调用(以及setState() )推到事件队列的末尾,让render()调用首先完成。
https://stackoverflow.com/questions/48226268
复制相似问题