使用componentDidUpdate在React中实现无限循环

5
我正在尝试创建一个基本的向导,包含3个步骤。在我的根文件中,在构造函数中设置了我的状态:
constructor(props) {
    super(props);
    this.state = {
      currentStep: 1,
      data: {
        firstname: 'James',
        surname: 'Smith',
        country: 'Australia',
      },
    };

我的向导有3个“步骤”,这是我如何渲染其中一个的示例:
<DataEntry currentStep={this.state.currentStep} data={this.state.data} afterValidate={this._nextStep} moveBack={this._prevStep} />

然后,在这一步中,我的构造函数是:
  constructor(props) {
    super(props);
    this.state = { data: this.props.data };
    this._validate = this._validate.bind(this);
    console.log(this.state);
  }

所以我根据传入的“数据”设置步骤的状态。
我的onChange是通用的,因此每个“字段”都有一个onchange,它会执行以下操作:
  onChange(fieldName, fieldValue) {
    const thisData = { ...this.state.data, [fieldName]: fieldValue };
    this.setState({ data: thisData });
  }

当我点击“下一步”按钮进入下一步时,我会在我的“步骤”组件中调用一个方法:
  _validate() {
    console.log('Validating...');
    this.props.afterValidate(this.state.data);
  }

这将调用我的父组件中的方法来更新数据:
  _nextStep(data) {
    console.log('Next');
    let currentStep = this.state.currentStep;
    console.log(currentStep);
    currentStep = currentStep >= 2 ? 3 : currentStep + 1;
    this.setState({ currentStep, data }, ()=>{console.log('New state: ', this.state)});
  }

这项工作。但问题在于,我似乎陷入了循环中,因为我需要在其他“步骤”组件中更新状态。每个步骤都有:
  componentDidUpdate() {
    console.log('Data Entry got Prop Update...');
    this.setState({ data: this.props.data });
  }

因此,当父级中的状态更新时,它需要更新步骤中的状态...但我似乎陷入了一个暴力循环:

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

我猜测它们都被调用了'componentDidUpdate',因为父级状态基本上更新了所有步骤,而它们反过来通知父级状态已更新?

实现这一点的正确方法是什么?基本上,我希望父级中的数据是真实的来源,然后每个“步骤”中的更新都更新此状态,并传播到步骤。

1个回答

10

这个问题已经在React文档中进行了描述:

componentDidUpdate(prevProps) {
  // Typical usage (don't forget to compare props):
  if (this.props.userID !== prevProps.userID) {
    this.fetchData(this.props.userID);
  }
}

你可以在componentDidUpdate()中立即调用setState(),但请注意必须将其包装在条件语句中,就像上面的示例一样,否则会导致无限循环。
有关更多信息,请参阅componentDidUpdate()
此外,为了比较prevProps和currentProps,您可以考虑使用Javascript中的对象比较
在javascript中有几种比较两个对象的方法。例如:
1)快速而受限制的方法
适用于没有方法和DOM节点的简单JSON样式对象:
JSON.stringify(obj1) === JSON.stringify(obj2)
属性的顺序很重要,所以对于以下对象,此方法将返回false:
 x = {a: 1, b: 2};
 y = {b: 2, a: 1};

这个例子来自于: JavaScript中的对象比较


1
谢谢。我注意到了那个评论,但是我不确定我应该检查什么。在这个例子中,他们检查一个字段。我需要遍历所有字段并查看它们是否更改了吗?或者可能添加一个字段来处理hasChanged? - Craig
我认为这可能会有所帮助:JavaScript中的对象比较 - You Nguyen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接