我试图通过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内的setState或 componentDidUpdate。 React将嵌套更新的数量限制为 防止无限循环。
我猜想正在为它们全部调用'componentDidUpdate',因为父状态基本上更新了所有步骤,然后它们又通知父状态已更新?
实现此目标的正确方法是什么?基本上,我希望父级中的数据成为真相的来源,然后在每个“步骤”中更新,以更新此状态,并传播到步骤。
答案 0 :(得分:5)
此问题已在React Document中进行了描述:
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)
属性的ORDER重要,因此此方法将为以下对象返回false:
x = {a: 1, b: 2};
y = {b: 2, a: 1};