所以我有一个对象数组,其中键是“成本”和“服务”,称为估计。您可以通过单击“添加”来添加到数组,这会向数组添加新索引 (i)。问题是在第一个周期中,我得到了一个很好的数组 {'cost': 2500, 'service': "commercial Cleaning"} (imgSet-1),但是当我添加另一个项目时,它完全删除了该数组并仅设置了其中一个嵌套对象的键和值。 (imgSet-2)。这是我在保存状态后寻找的结果(imgSet-3),我尝试使用@RubenSmn 方法,但随后收到此错误。 (imgSet-4)
imgSet-1 ********* 添加初始服务 初始服务添加的结果
imgSet-2 ********* 添加第二个服务 第二次添加服务的结果
下面是页面部分的代码,您可以在其中添加服务和文本输入的输出。
const [estimate, setEstimate] = useState([]);
{[...Array(numServices)].map((e, i) => {
return (
<div key={i} className="flex justify-between">
<div>
<NumericTextBoxComponent
format="c2"
name={`cost-${i}`}
value={estimate?.items?.["cost"]?.[i]}
change={(e) =>
setEstimate({ ...estimate, items: [{...estimate?.items?.[i],cost: e?.value}]})
}
placeholder='Price'
floatLabelType="Auto"
data-msg-containerid="errorForCost"
/>
</div>
<div>
<DropDownListComponent
showClearButton
fields={{ value: "id", text: "service" }}
name={`service-${i}`}
value={estimate?.items?.["service"]?.[i]}
change={(e) =>
setEstimate({ ...estimate, items: [{...estimate?.items?.[i],service: e?.value}]})
}
id={`service-${i}`}
floatLabelType="Auto"
data-name={`service-${i}`}
dataSource={estimateData?.services}
placeholder="Service"
data-msg-containerid="errorForLead"
></DropDownListComponent>
<div id="errorForLead" />
</div>
</div>
);
})}
</form>
<button onClick={() => setNumServices(numServices + 1)}>Add</button>
我尝试了多种不同的扩展运算符,但我似乎无法让它工作。我的预期结果是:
estimate:{
items: [
{'cost': 2500, 'service': 'Commercial Clean'},
{'cost': 500, 'service': 'Bathroom Clean'},
{'cost': 180, 'service': 'Apartment Clean'},
{etc.}
]
}
初始状态是一个数组,它不是您在
change
处理程序中设置的对象。你可以有这样的初始状态。
const [estimate, setEstimate] = useState({ items: [] });
设置新状态时,您不会添加回状态的旧项目。
setEstimate({
...estimate,
items: [{ ...estimate?.items?.[i], cost: e?.value }],
// should be something like
// items: [...estimate.items, { ...estimate.items?.[i], cost: e?.value }],
});
但是你不能这样做,因为每次更改值时它都会在你的 items 数组中创建一个新对象。
我制作了这个动态
handleChange
函数,您可以使用它来更改状态。第一个 if 语句是检查 itemIndex 是否已在 items 数组中。如果没有,请使用 propertyName
和 value
创建一个新项目
const handleChange = (e, itemIndex, propertyName) => {
const newValue = e?.value;
setEstimate((prevEstimate) => {
if (prevEstimate.items.length <= itemIndex) {
const newItem = { [propertyName]: newValue };
return {
...prevEstimate,
items: [...prevEstimate.items, newItem]
};
}
// loop over old items
const newItems = [...prevEstimate.items].map((item, idx) => {
// if index' are not the same just return the old item
if (idx !== itemIndex) return item;
// else return the item with the new service
return { ...item, [propertyName]: newValue };
});
return {
...prevEstimate,
items: newItems,
};
});
};
对于服务下拉列表,您可以对成本执行相同的操作,只需更改属性名称
<DropDownListComponent
...
value={estimate.items[i]?.service}
change={(e) => handleChange(e, i, "service")}
...
></DropDownListComponent>
在这里查看简化版实时版本