我在这里看到了类似的问题,但到目前为止这些问题没有帮助。
我有一个具有数组状态的组件:
eventData: []
一些逻辑监视事件并将对象推送到状态数组:
eventData.unshift(result.args);
this.setState({ eventData });;
unshift()
用于将新元素推到数组顶部。
我要实现的是渲染状态数组的内容。我编写了一个条件,该条件检查某个状态,并根据该状态决定要输出的内容。
let allRecords;
if (this.state.allRecords) {
for (let i = 0; i < this.state.eventData.length; i++) {
(i => {
allRecords = (
<div className="event-result-table-container">
<div className="result-cell">
{this.state.eventData[i].paramOne}
</div>
<div className="result-cell">
{() => {
if (this.state.eventData[i].paramTwo) {
<span>Win</span>;
} else {
<span>Loose</span>;
}
}}
</div>
<div className="result-cell">
{this.state.eventData[i].paramThree.c[0]}
</div>
<div className="result-cell">
{this.state.eventData[i].paramFour.c[0]}
</div>
<div className="result-cell">
{this.state.eventData[i].paramFive.c[0] / 10000}
</div>
<div className="result-cell-last">
{this.state.eventData[i].paramSix.c[0]}
</div>
</div>
);
}).call(this, i);
}
} else if (!this.state.allRecords) {
for (let i = 0; i < this.state.eventData.length; i++) {
if (this.state.account === this.state.eventData[i].paramOne) {
(i => {
allRecords = (
<div className="event-result-table-container">
<div className="result-cell">
{this.state.eventData[i].paramOne}
</div>
<div className="result-cell">
{() => {
if (this.state.eventData[i].paramTwo) {
<span>Win</span>;
} else {
<span>Loose</span>;
}
}}
</div>
<div className="result-cell">
{this.state.eventData[i].paramThree.c[0]}
</div>
<div className="result-cell">
{this.state.eventData[i].paramFour.c[0]}
</div>
<div className="result-cell">
{this.state.eventData[i].paramFive.c[0] / 10000}
</div>
<div className="result-cell-last">
{this.state.eventData[i].paramSix.c[0]}
</div>
</div>
);
}).call(this, i);
}
}
}
这段代码存在的问题:
eventData
状态对象的最后一个值。bool
获得console.log
的值,所以我知道该值在那里)这甚至是实现所需的最有效方法吗?我也在考虑通过元素进行映射,但是决定坚持使用for循环。
感谢您的帮助。
答案 0 :(得分:1)
几件事:
首先,正如上面的评论所指出的,不使用setState
来更改状态与React的工作方式背道而驰,解决此问题的最简单解决方案是执行以下操作:
this.setState(prevState => ({
eventData: [...prevState.eventData, result.args]
}));
此处的代码有问题。箭头函数从未被调用过吗?
{() => {
if (this.state.eventData[i].paramTwo) {
<span>Win</span>;
} else {
<span>Loose</span>;
}
}
}
此功能可以简化为以下功能(应用下面的代码中的解构之后):
<span>{paramTwo ? 'Win' : 'Lose'}</span>
接下来,通过映射删除函数中的重复项。通过在适当的位置设置条件并使用三元数,可以将代码简化为以下内容,并将其直接包含在render函数的JSX部分中:
render(){
return(
<div> //Could also be a fragment or anything
{this.state.allRecords || this.state.account === this.state.eventData[i].paramOne &&
this.state.eventData.map(({ paramOne, paramTwo, paramThree, paramFour, paramFive, paramSix }, i) =>
<div className="event-result-table-container" key={i}> //Don't forget the key like I just did before editing
<div className="result-cell">
{paramOne}
</div>
<div className="result-cell">
<span>{paramTwo ? 'Win' : 'Lose'}</span>
</div>
<div className="result-cell">
{paramThree.c[0]}
</div>
<div className="result-cell">
{paramFour.c[0]}
</div>
<div className="result-cell">
{paramFive.c[0] / 10000}
</div>
<div className="result-cell-last">
{paramSix.c[0]}
</div>
</div>
)
}
</div>
)
}
最后,仅获取数组的前20个元素,请使用slice:
this.state.eventData.slice(0, 20).map(/* CODE ABOVE */)
编辑:
对不起,在理解您在渲染中使用的条件时,我犯了一个错误,这是代码开头的固定版本:
{this.state.allRecords &&
this.state.eventData.filter(data => this.state.account === data.paramOne).slice(0, 20).map(/* CODE ABOVE */)
在这里,我们使用filter
仅使用符合给定条件的数组元素。
编辑2:
我刚刚犯了另一个错误,希望是最后一个错误。这应该具有正确的逻辑:
this.state.eventData.filter(data => this.state.allRecords || this.state.account === data.paramOne).slice(0, 20).map(/* CODE ABOVE */)
如果定义了this.state.allRecords
,它将接受所有内容;否则,它将检查您的状况。
答案 1 :(得分:0)
我清理了一下并重构了您的代码。我为重复逻辑编写了一个通用函数,然后将循环对象传递给通用函数以进行渲染。
使用Map代替forloops。您确实需要检查此this.state.account === this.state.eventObj.paramOne
语句。这可能是您在屏幕上仅看到一项的原因。
请共享一些伪数据和unshift
部分后面的逻辑(切勿直接在状态对象上进行操作),我们将对其进行修复。
getRecord = (eventObj) => (
<React.Fragment>
<div className="result-cell">
{eventObj.paramOne}
</div>
<div className="result-cell">
{eventObj.paramTwo ? <span>Win</span> : <span>Loose</span>}
</div>
<div className="result-cell">
{eventObj.paramThree.c[0]}
</div>
<div className="result-cell">
{eventObj.paramFour.c[0]}
</div>
<div className="result-cell">
{eventObj.paramFive.c[0] / 10000}
</div>
<div className="result-cell-last">
{eventObj.paramSix.c[0]}
</div>
</React.Fragment>
)
render() {
let allRecords;
if (this.state.allRecords) {
allRecords = <div>{this.state.eventData.map(eventObj => this.getRecord(eventObj)}</div>;
} else if (!this.state.allRecords) {
allRecords = <div>{this.state.eventData.map(eventObj => {
if (this.state.account === this.state.eventObj.paramOne) {
return this.getRecord(eventObj);
}
return null;
})}</div>;
}
return (<div className="event-result-table-container">{allRecords}</div>);
}