首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从render方法调用React中的setState()

从render方法调用React中的setState()
EN

Stack Overflow用户
提问于 2018-01-12 20:25:21
回答 3查看 27.2K关注 0票数 10

我正在尝试使用setState()方法重置容器中的React状态变量(为默认值)。但是得到以下错误

代码语言:javascript
复制
 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`.

最后:超过了最大调用堆栈大小。

我的代码如下:

代码语言:javascript
复制
resetMsg=()=>  {  
const company = this.state.company;
company.id = 0;
company.messages = [];    
this.setState({company: company});       
}

当Redux状态下的变量为真时,我调用resetMsg()。

我调用resetMsg的代码( resetMessages的值最初为false,当它为true时,我需要重置React-state ):

代码语言:javascript
复制
    render() {
    if(this.props.resetMessages){           
        this.resetMsg();           
    }
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-01-12 20:54:08

您可能需要查看componentWillReceiveProps(nextProps)函数。根据官方文件:

在挂载的组件接收新的属性之前,会调用

componentWillReceiveProps()。如果您需要更新状态以响应适当的更改(例如,重置它),您可以比较this.props和nextProps,并在此方法中使用this.setState()执行状态转换。

这是您想要进行重置的位置。所以就像这样:

代码语言:javascript
复制
componentWillReceiveProps(nextProps) {
  if(nextProps.resetMessages) {
    const company = Object.assign({}, this.state.company);
    company.id = 0;
    company.messages = [];    
    this.setState({company: company});
  }
}

每次将道具发送到组件时,都会运行上面的代码片段。它首先检查resetMessages属性是否真实。如果是,它将创建company状态的临时副本,更改idmessages属性值,然后使用新的属性更新company

我想强调一下您在代码中遇到的问题:

  1. render()内部调用setState()是个禁忌。

在一般情况下,只要调用setState()render()就会随后运行。在render()内部执行此操作将导致该函数一次又一次地被调用,并直接again...

  • Mutating状态和/或属性。

这一行const company = this.state.company;不会创建状态变量的副本。它只存储对它的引用。所以一旦你这样做了,然后再做company.id = ...,你实际上就是在做this.state.company.id = ...,这是React中的反模式。我们只通过setState()来改变状态。

要创建副本,请对对象使用Object.assign({}, this.state.yourObject),对数组使用this.state.yourArray.slice()

票数 18
EN

Stack Overflow用户

发布于 2018-08-26 16:11:42

componentWillReceiveProps现在是弃用的(自18年6月以来)

您应该使用react docs中提供的备选方案之一。

在您的情况下,我猜使用使用getDerivedStateFromProps的“不推荐的”替代版本1是合理的,因为您只是在重新计算状态变量:

代码语言:javascript
复制
getDerivedStateFromProps(props, state) {
  if(props.resetMessages) {
    const company = Object.assign({}, state.company);
    company.id = 0;
    company.messages = [];    
    return {
      company: company
   }
}
票数 10
EN

Stack Overflow用户

发布于 2021-12-29 20:50:43

尝试延迟setState()调用,直到渲染完成。您可以使用setTimeout()来实现此目的。例如,而不是:

代码语言:javascript
复制
this.resetMsg()

使用

代码语言:javascript
复制
setTimeout(() => this.resetMsg())

这将把resetMsg()调用(以及setState() )推到事件队列的末尾,让render()调用首先完成。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48226268

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档