我正在映射一个对象,根据当前映射对象的值(1或大于1(,它将转到相应的If函数。
我正在尝试更新状态,以了解有多少对象元素符合给定的需求。
const displayMovements = () => {
return(
movements.map((m) => {
if (m.value === 1) {
setAmountEqualToOne(amountEqualToOne + 1)
return(
<DisplayTemplateOne prop={m}/>
)
} else if (m.value > 1) {
setAmountGreaterThanOne(amountGreaterThanOne + 1)
return(
<DisplayTemplateTwo prop={m}/>
)
}
})
)
}
我遇到了一个无限循环错误,不确定下一步该去哪里。
本质上,这里的问题是在渲染时更新状态。更新状态会触发重新渲染。所以周期是:
- 渲染组件
- 更新状态的
- 重新渲染组件
- 更新状态的
- 等等
(顺便说一句,状态更新也被破坏了。状态更新是异步的,所以这些更新是排队的,最终只会在这里进行最后一次。不要在循环中更新状态,而是计算新状态,并在循环后更新一次。但这是另一个问题。(
因此,从根本上讲,不要在每次渲染时都更新状态。但问题来了,你为什么要这么做?目标是什么?
我正在尝试更新状态,以了解有多少对象元素符合给定的要求。
不要将其存储在状态中。这是一个从状态计算的值,而不是存储在中的。在渲染组件时,您可以简单地进行计算。类似这样的东西:
const amountEqualToOne = movements.filter(m => m.value === 1).length;
const amountGreaterThanOne = movements.filter(m => m.value > 1).length;
return(
movements.map(m =>
m.value === 1 ? <DisplayTemplateOne prop={m}/> :
m.value > 1 ? <DisplayTemplateTwo prop={m}/> :
null)
);
上面还纠正了一个潜在的问题,即传递给.map()
的回调并不总是返回值。在这种情况下,它将至少显式地返回null
作为默认情况,而不是undefined
。
但在这种情况下,无论您打算在哪里使用amountEqualToOne
和amountGreaterThanOne
,都会在每次渲染时重新计算它们,并且可以使用。
将计算值有效地存储在状态中意味着将相同的信息存储在两个不同的状态值中两次,并且需要手动保持这些值的同步。这是一大堆你并不想要的麻烦。