我试图使用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`.
Run Code Online (Sandbox Code Playgroud)
最后:超出最大调用堆栈大小.
我的代码如下:
resetMsg=()=> {
const company = this.state.company;
company.id = 0;
company.messages = [];
this.setState({company: company});
}
Run Code Online (Sandbox Code Playgroud)
当Redux状态的变量为true时,我调用resetMsg().
我调用resetMsg的代码(resetMessages的值最初为false,我需要重置React-state,当它为true时):
render() {
if(this.props.resetMessages){
this.resetMsg();
}
Run Code Online (Sandbox Code Playgroud)
Chr*_*ris 15
您可能想要查看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});
}
}
Run Code Online (Sandbox Code Playgroud)
每次将道具发送到组件时,上面的代码段都会运行.它首先检查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()数组.
componentWillReceiveProps已弃用(自18年6月以来)
您应该使用react docs中提供的替代方法之一。
在您的情况下,我猜想使用使用getDerivedStateFromProps的“不那么推荐”替代版本1是合理的,因为您只是在重新计算状态vars:
getDerivedStateFromProps(props, state) {
if(props.resetMessages) {
const company = Object.assign({}, state.company);
company.id = 0;
company.messages = [];
return {
company: company
}
}
Run Code Online (Sandbox Code Playgroud)