使用shouldComponetUpdate打破状态集循环?

时间:2017-01-14 20:15:28

标签: javascript reactjs state

我正在开发一个反应应用程序,偶然发现如果我不使用shouldComponentUpdate()阻止我的组件不断相互更新的情况。我试图确定这是否是处理此类更改的最佳方式,或者我是否应该尝试重构我的代码,因此我不必以这种方式停止更新。

我的实际代码中充满了许多其他的东西,所以我把几个虚拟的例子放在一起。

父组件:

    class App extends React.Component {
      constructor() {
        super();

        this.stateChange = this.stateChange.bind(this);

        this.state = {
          foo: 'bar'
        }
      }


      stateChange(change) {
        this.setState({foo: change});
      }

      render() {
        return (
          <div>
            <p>Hello World</p>
            <ChildComponent stateChange={this.stateChange} />
          </div>
          )
      }

    }

子组件:

    class ChildComponent extends React.Component {
      constructor() {
        super();

        this.renderDecision = this.renderDecision.bind(this);
        this.updateStage = this.updateStage.bind(this);
        this.state = {
          stage: [1],
          hello: 'world'
        }
      }

      updateStage(e) {
          let theStage = [...this.state.stage];
          theStage.push(1);
          this.setState({stage: theStage});
        }

      renderDecision() {

        if (this.state.stage.length < 3) {
          return (
            <p>There are {this.state.stage.length} items. <button onClick={(e) => this.updateStage(e)}>Click here to update.</button></p>
            )
        } else if (this.state.stage.length === 3) {
          this.props.stateChange(this.state.hello); /// updates the parent which updates the child which updates the parent... ad infinitum
          return (
            <p>Hello {this.state.hello}, there are {theStage} items.</p>
          )
        }
      }

      render() {
        return (
          <div>
            (this.renderDecision())
          </div>
        )
      }
    }

正如您所看到的,一旦stage阵列达到长度3并保持在那里,应用程序&amp;子组件被锁定在设置状态的循环中。

可以通过向ChildComponent -

添加类似的内容来解决此问题
      componentShouldUpdate() {
        if (this.state.stage.length === 3) {
          return false;
        } else return true;
      }

但我想知道的是这是否是最佳做法,或者我是否应该提出其他解决方案。我的子组件具有状态,因为它会快速连续地循环显示大约6个不同的参数,而应用程序的其余部分不必知道正在进行的操作,因此通过以下方式重新呈现整个应用程序是没有意义的。将stage一直传递给父母。

希望这个问题有道理。谢谢你的阅读。

2 个答案:

答案 0 :(得分:1)

你永远不应该改变渲染状态,检查这个issue。 在渲染之外做出那些州决定和人口。

答案 1 :(得分:1)

你在做什么根本不正确。试想看反应如何更新DOM。只要组件的状态发生变化,就会调用组件的render方法。

在组件中,只要调用render方法,就会触发更新状态(renderDecision)的函数。因此,当调用render时,状态会更新,并且由于状态已更新,因此再次调用render。这迫使无限循环。

解决方案

使用适当的生命周期方法或事件(例如onClick)来更新状态。我的情况你可以在componentDidMount或componentWillMount

中设置状态