从渲染方法调用 React 中的 setState() [英] Calling setState() in React from render method

查看:60
本文介绍了从渲染方法调用 React 中的 setState()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to reset React state variables (to default values) in a container using setState() method. But getting the following error

 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`.

最后:超出最大调用堆栈大小.

And finally: Maximum call stack size exceeded.

我的代码如下:

resetMsg=()=>  {  
const company = this.state.company;
company.id = 0;
company.messages = [];    
this.setState({company: company});       
}

当 Redux 状态中的变量为真时,我正在调用 resetMsg().

I am calling resetMsg() when variable in Redux state is true.

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

Code where I call resetMsg (The value of resetMessages is false initially and I need to reset React-state, when its true ):

    render() {
    if(this.props.resetMessages){           
        this.resetMsg();           
    }

推荐答案

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

You might want to look into componentWillReceiveProps(nextProps) function. As per the official docs:

componentWillReceiveProps() 在挂载的组件接收新的 props 之前被调用.如果您需要更新状态以响应 prop 更改(例如重置它),您可以比较 this.props 和 nextProps 并在此方法中使用 this.setState() 执行状态转换.

componentWillReceiveProps() is invoked before a mounted component receives new props. If you need to update the state in response to prop changes (for example, to reset it), you may compare this.props and nextProps and perform state transitions using this.setState() in this method.

这是您要进行重置的地方.所以像:

This is where you want to do the resets. So something like:

componentWillReceiveProps(nextProps) {
  if(nextProps.resetMessages) {
    const company = Object.assign({}, this.state.company);
    company.id = 0;
    company.messages = [];    
    this.setState({company: company});
  }
}

每次 props 被发送到组件时,上面的代码片段都会运行.它首先检查 resetMessages 属性是否为真.如果是,它将创建 company 状态的临时副本,更改 idmessages 属性值,然后更新 公司与新公司.

The snippet above will run every time props are sent down to the component. It first checks if the resetMessages prop is truthy. If it is, it will create a temporary copy of the company state, change the id and messages property values, and then update company with the new one.

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

I want to highlight the issues you had with your code:

  1. render() 中调用 setState() 是一个禁忌.

  1. Calling setState() inside render() is a no-no.

每当您调用 setState() 时,通常 render() 都会在之后运行.在 render() 内部这样做会导致该函数被一次又一次地调用......

Whenever you call setState() in general the render() will be run afterwards. Doing so inside render() itself will cause that function to be called again, and again, and again...

直接改变状态和/或道具.

Mutating the state and/or props directly.

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

This line const company = this.state.company; does not create a copy of the state variable. It only store the reference to it. So once you do this, and then do company.id = ... you are essentially doing this.state.company.id = ..., which is anti-pattern in React. We only ever change state through setState().

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

To create a copy, use Object.assign({}, this.state.yourObject) for objects and this.state.yourArray.slice() for arrays.

这篇关于从渲染方法调用 React 中的 setState()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆