我经常遇到无限循环问题,不知道为什么。
我正在使用reactJS 16.5.2
当您在不允许的地方(例如在render方法中)编写SetState时,通常会发生循环。
我正在遵循本指南:https://medium.com/@baphemot/understanding-reactjs-component-life-cycle-823a640b3e8d 注意这个问题。
我制作了多个HOC(装饰器/包装器)组件,将通用方法集中在一个点上,并使用道具将其传播给每个孩子。
通常效果很好。
我试图简化下面的组件结构。
问题在于FORM及其子级。 输入之一具有DropDown,必须使用上层包装程序的方法填充该DropDown。我将调用放在componentDidMount中(如上面的链接所示)。不幸的是,包装器setState似乎触发了FORM Component的完整描述和重新构建。我在从包装到表单的每个构造函数中放置一个console.log。仅重新创建FORM及其所有输入(而不更新)。
此重新创建会产生无限循环,因为每次都会触发componentDidMount。
我不知道该如何解决。我检查了每个“键”属性,所有组件都有其唯一的键。我问你为什么要重新创建而不是更新?
是由于父渲染中的表单构建方法吗?如果是这样,那么使用异步数据填充构建表单的正确设计模式是什么?
答案 0 :(得分:2)
简化生活,而不是创建一堆包装器,只需创建一个将以相同方式运行的container-component
即可。例如,您将创建一个关心container
和data
的{{1}},然后与可重用子项state
共享它和它的方法(如下所示,两者都可以一样)。
这与从API提取的数据完全相同。您将在component
中检索数据,将其设置为componentDidMount
,然后将state
传递给可重用组件。
您可以对可重用组件进行超级细化。例如,一个唯一可重复使用的按钮是提交表单。或者是可重复使用的输入,只能捕获1到100之间的数字,依此类推。
如果组件嵌套过多,请考虑使用redux。
工作示例:https://codesandbox.io/s/x2ol8wmzrp
containers / Form.js (容器组件)
state
components / Fields.js (可重用组件)
import React, { Component } from "react";
import Fields from "../components/Fields";
export default class Form extends Component {
state = {
buttonFields: [
{ id: "Apples", quantity: 1 },
{ id: "Strawberries", quantity: 1 },
{ id: "Grapes", quantity: 1 },
{ id: "Apricots", quantity: 1 }
]
};
handleButtonClick = id => {
this.setState(prevState => ({
buttonFields: prevState.buttonFields.map(
item =>
id === item.id ? { id, quantity: item.quantity + 1 } : { ...item }
)
}));
};
render = () => (
<Fields
{...this.state}
onButtonClick={this.handleButtonClick}
title="Container Component"
/>
);
}
containers / Wrapper.js (不必要的包装器)
import React from "react";
export default ({ buttonFields, onButtonClick, title }) => (
<div className="container">
<h1 style={{ textAlign: "center" }}>{title}</h1>
{buttonFields.map(({ id, quantity }) => (
<button
style={{ marginRight: 10 }}
className="uk-button uk-button-primary"
key={id}
onClick={() => onButtonClick(id)}
>
{id} ({quantity})
</button>
))}
</div>
);
答案 1 :(得分:0)
感谢马特·卡洛塔(Matt Carlotta)的回答,我找出了问题所在。
在上图中,我简化了太多,所以我错过了一个重要的声明。
在我创建SomeFormComponent的“ FinalComponent”中,由于其包装,我正在执行以下操作:
renderForm()
{
var WrappedFormComponent = FormHOC(SomeFormComponent();
return <WrappedFormComponent {...this.props} [...] />
}
很明显,使用该语法,由于render方法中调用了renderForm方法,因此每次都会实例化Form。
解决方案非常简单。我将该行移到了组件上方:
const WrappedFormComponent = FormHOC(SomeFormComponent();
export default class FinalComponent extends React.Component