为啥不能在渲染方法中改变状态。在调用渲染方法之前更改状态的最佳位置是啥

Posted

技术标签:

【中文标题】为啥不能在渲染方法中改变状态。在调用渲染方法之前更改状态的最佳位置是啥【英文标题】:why Can't change the state in the render method. What is the best place to change the state before calling render method为什么不能在渲染方法中改变状态。在调用渲染方法之前更改状态的最佳位置是什么 【发布时间】:2020-08-07 10:22:13 【问题描述】:

我正在尝试在 render 方法中进行状态更改,但它显示:

错误:超过最大更新深度。当组件在 componentWillUpdate 或 componentDidUpdate 中重复调用 setState 时,可能会发生这种情况。 React 限制了嵌套更新的数量以防止无限循环。

class Test extends Component 
    state =  
        name:[],

    



    render() 
        this.setState(name:this.props.data)


        return(
          <div>
              this.state.name.map(e=>(
                  <h3>e</h3>
              ))
          </div>
      );  
    

【问题讨论】:

你不能这样做,因为setState调用了render,render调用了setState等等……你最终会陷入死循环。 是的。我想知道在渲染 dom 之前更新状态的最佳位置是什么。 但是你为什么要用已经处于状态的数据来更新状态呢? :) 通常在 React 中,您使用事件处理程序来更新状态。 道具呢?如果有我必须更新到当地状态的道具? 这是一些精简的例子,还是你真的想这样做?直接从道具渲染,即this.props.data.map(e =&gt; &lt;h3&gt;e&lt;/h3&gt;) 【参考方案1】:

您不能在渲染函数中设置反应状态,但可以在构造函数或大部分组件生命周期函数中设置。

在构造函数中设置一些初始状态

class Test extends Component 
  constructor(props) 
    super(props);
    this.state = 
      name: props.data,
    ;
  

  render() 
    return (
      <div>
        this.state.name.map(e => (
          <h3>e</h3>
        ))
      </div>
    );
  

或者在生命周期函数中设置状态

class Test extends Component 
  state = 
    name: [],
  ;

  componentDidMount() 
    this.setState( name: this.props.data );
  

  render() 
    return (
      <div>
        this.state.name.map(e => (
          <h3>e</h3>
        ))
      </div>
    );
  

【讨论】:

【参考方案2】:

永远不要在渲染函数中设置状态,因为它可能会产生副作用,最终会产生无限渲染循环。每次状态发生变化时,React 都会调用 render() 函数。在基于用户与 UI 的交互调用的事件处理函数中的渲染函数之外设置状态。

下面的示例是一个基于函数的组件,当用户单击按钮时,它会更改按钮文本。

const DemoApp = (props) => 
          const [state, setState] = useState(false);

          const handleButtonPress = () => 
          setState(true);
          

return(
      <Button
          onPress=handleButtonPress
          title=state ? 'Pressed' : 'click Here'
          color="#841584"

      />
     )  

【讨论】:

【参考方案3】:

可能存在对象的状态取决于不断变化的道具的情况。在这种情况下,getDerivedStateFromProps 方法可以派上用场。在this page 上给出了实现。以下是该方法的使用方法:

  constructor(props) 
    super(props);
    this.state = favoritecolor: "red";
  
  static getDerivedStateFromProps(props, state) 
    return favoritecolor: props.favcol ;
  
  render() 
    return (
      <h1>My Favorite Color is this.state.favoritecolor</h1>
    );
  


ReactDOM.render(<Header favcol="yellow"/>, document.getElementById('root'));

此实现取自上述链接。它当然提供了一种替代方法来更改渲染方法中的状态。

【讨论】:

以上是关于为啥不能在渲染方法中改变状态。在调用渲染方法之前更改状态的最佳位置是啥的主要内容,如果未能解决你的问题,请参考以下文章

为啥渲染方法在类组件中运行两次而没有包含任何状态?

Flutter:状态类:为啥不在 setState 方法调用之前改变状态变量,而不是在 setState 方法中

即使状态没有改变,为啥 setState 会导致太多的重新渲染错误

为啥 redux 状态不能正确渲染?

为啥组件在单击和状态更改时会重新渲染?

地图渲染 优化方法