【问题标题】:React infinite loop using componentDidUpdate使用 componentDidUpdate 反应无限循环
【发布时间】:2018-10-07 00:58:07
【问题描述】:

我正在尝试通过 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 });
  }

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

未捕获的错误:超出最大更新深度。这可能发生在一个 组件在 componentWillUpdate 内重复调用 setState 或 组件更新。 React 将嵌套更新的数量限制为 防止无限循环。

我猜他们都调用了“componentDidUpdate”,因为父状态基本上更新了所有步骤,而它们又通知父状态更新了?

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

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    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,你可以考虑Object Comparison in Javascript

    在 javascript 中有几种方法可以比较两个对象。例如:

    1) 快速且有限的方法

    当您有简单的 JSON 样式对象而内部没有方法和 DOM 节点时有效:

    JSON.stringify(obj1) === JSON.stringify(obj2)

    属性的顺序很重要,因此此方法将为以下对象返回 false:

     x = {a: 1, b: 2};
     y = {b: 2, a: 1};
    

    本例摘自:Object comparison in JavaScript

    【讨论】:

    • 谢谢。我确实注意到了那个评论。但我不确定我会检查什么。在示例中,他们检查一个字段。我是否需要遍历所有字段并查看它们是否更改?或者可能添加一个字段来处理 hasChanged?
    • 我认为这可能会有所帮助:Object Comparison in Javascript
    猜你喜欢
    • 1970-01-01
    • 2021-08-26
    • 2021-07-12
    • 2020-03-13
    • 2016-10-22
    • 2021-05-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多