编辑对象状态的数组



我有一个存储在状态中的对象数组,状态中包含的信息取决于产品,例如:

例如,一个产品可能包含2个尺寸,阵列看起来像这样:

const [sizes, setSizes] = useState([
{
size: 'S',
colors: [
{
color: 'red',
stock: 10
},
{
color: 'blue',
stock: 15
}
]
},
{
size: 'M',
colors: [
{
color: 'yellow',
stock: 10
},
{
color: 'blue',
stock: 15
}
]
}
])

但如果产品包含4个(每个可能的尺寸(尺寸,则状态看起来像:

const [sizes, setSizes] = useState({
{
size: 'S',
colors: [
{
color: 'red',
stock: 10
},
{
color: 'blue',
stock: 15
}
]
},
{
size: 'M',
colors: [
{
color: 'yellow',
stock: 10
},
{
color: 'blue',
stock: 15
}
]
},
{
size: 'L',
colors: [
{
color: 'yellow',
stock: 10
},
{
color: 'blue',
stock: 15
}
]
},
{
size: 'XL',
colors: [
{
color: 'yellow',
stock: 10
},
{
color: 'blue',
stock: 15
}
]
}
})

现在JSX看起来像:

const allsizes = ['S', 'M', 'L', 'XL']
const colornames = [
"Beige",
"Black",
"Blue",
"Brown",
"Gray",
"Grey",
"Green",
'Red',
'Purple',
'Navy',
'Burgundy',
'White',
'Yellow'
];
const allsizesrow = allsizes.map(size=> {
return (
<span className={sizes?.some(x=> x.size === size)?'editsize selectededitsize':'editsize'}>
<AccordionTab title={size}>
<div className="colors">
{
colornames.map(color=> {
return (
<div className='sizelabel'>
<span>{color}:</span>
<input 
onChange={(e)=> handleChange(e, size, color)}
value={sizes?.find(x=> x.size === size)?.colors.find(x=> x.color === color.toLowerCase())?.stock}
type="number" 
/>
</div>
)
})
}
</div>
</AccordionTab>
</span>
)
})

CCD_ 1函数是我遇到的问题,它采用3个参数,即新库存编号(e(、与输入相关联的颜色(颜色(和与输入相关的尺寸(尺寸(。

我想做的是更新setSizes状态。

这是我为这个功能做的设置:

const handleChange = (e, size, color) => {
const sizeExists = sizes?.some(x=> x.size === size)
if(sizeExists) {
const colorExists = sizes?.find(x=> x.size === size).colors.some(x=> x.color === color.toLowerCase())
if(colorExists) {
//update the stock of the color associated with the size

}
//color doesnt exist but size exists
else {
//add the object of the color associated with the new stock to the appropriate selected size object
}
}
//size does not exist
else {
//add the selected size object along with a colors array containing the color that has a new value as an object inside the colors array of that size
}

}

任何我如何实时更新状态的想法,然后将用于更新数据库中的新信息。

虽然我看到这个问题已经得到了回答,但我想把这个答案放在这里,因为我使用了一个实用程序包immer(获奖(,它有助于以可变的方式更新状态,并负责从中返回新状态(它不会更新现有状态(。其好处是,对于复杂的对象/数组数据结构,更容易更新/插入/变异结构,并且代码行更少,可以提高维护和可读性。

你可以在这里找到我的代码沙盒。

你可以在这里获得包裹的详细信息

import produce from "immer";
....
const handleChange = (e, size, Color) => {
const color = Color.toLowerCase();
const exisingSize = sizes?.find((s) => s.size === size);
if (exisingSize) {
const existingColor = exisingSize.colors.find((c) => c.color === color);
if (existingColor) {
//update the stock of the color associated with the size
const nextSize = produce(sizes, (draftSizes) => {
draftSizes
.find((s) => s.size === size)
.colors.find((c) => c.color === color).stock = +e.target.value;
});
setSizes(nextSize);
}
//color doesnt exist but size exists
else {
//add the object of the color associated with the new stock to the appropriate selected size object
const nextSize = produce(sizes, (draftSizes) => {
draftSizes
.find((s) => s.size === size)
.colors.push({ color, stock: +e.target.value });
});
setSizes(nextSize);
}
}
//size does not exist
else {
//add the selected size object along with a colors array containing the color that has a new value as an object inside the colors array of that size
const nextSize = produce(sizes, (draftSizes) => {
draftSizes.push({ size, colors: [{ color, stock: +e.target.value }] });
});
setSizes(nextSize);
}
};

完整代码

import { useEffect, useState } from "react";
import produce from "immer";
const ColorSize = () => {
const [sizes, setSizes] = useState([
{
size: "S",
colors: [
{
color: "red",
stock: 10
},
{
color: "blue",
stock: 15
}
]
},
{
size: "M",
colors: [
{
color: "yellow",
stock: 10
},
{
color: "blue",
stock: 15
}
]
}
]);
const allsizes = ["S", "M", "L", "XL"];
const colornames = [
"Beige",
"Black",
"Blue",
"Brown",
"Gray",
"Grey",
"Green",
"Red",
"Purple",
"Navy",
"Burgundy",
"White",
"Yellow"
];
const handleChange = (e, size, Color) => {
const color = Color.toLowerCase();
const exisingSize = sizes?.find((s) => s.size === size);
if (exisingSize) {
const existingColor = exisingSize.colors.find((c) => c.color === color);
if (existingColor) {
//update the stock of the color associated with the size
const nextSize = produce(sizes, (draftSizes) => {
draftSizes
.find((s) => s.size === size)
.colors.find((c) => c.color === color).stock = +e.target.value;
});
setSizes(nextSize);
}
//color doesnt exist but size exists
else {
//add the object of the color associated with the new stock to the appropriate selected size object
const nextSize = produce(sizes, (draftSizes) => {
draftSizes
.find((s) => s.size === size)
.colors.push({ color, stock: +e.target.value });
});
setSizes(nextSize);
}
}
//size does not exist
else {
//add the selected size object along with a colors array containing the color that has a new value as an object inside the colors array of that size
const nextSize = produce(sizes, (draftSizes) => {
draftSizes.push({ size, colors: [{ color, stock: +e.target.value }] });
});
setSizes(nextSize);
}
};
useEffect(() => {
console.log(sizes);
}, [sizes]);
const allsizesrow = allsizes.map((size) => {
return (
<span>
<h3>{size}</h3>
<div>
{colornames.map((color) => {
return (
<div>
<span>{color}:</span>
<input
onChange={(e) => handleChange(e, size, color)}
value={
sizes
?.find((x) => x.size === size)
?.colors.find((x) => x.color === color.toLowerCase())
?.stock
}
type="number"
/>
</div>
);
})}
</div>
</span>
);
});
return <>{allsizesrow}</>;
};
export default ColorSize;
if(sizeExists){    
if(colorExists) {
let tempState=[...sizes]
let indexOfSize =tempState.findIndex(x => x.size ==size);
let indexOfColor=tempState[indexOfSize].findIndex(x => x.color ===color)
tempState[indexOfSize].colors[indexOfColor].stock=e.target.value
setSizes(tempState)
} else {
let tempState=[...sizes]
let indexOfSize =tempState.findIndex(x => x.size ==size);
tempState.colors.push({color:color,stock:e.target.value})
setSizes(tempState)
}
} else {    //if size does not exist
let tempState=[...sizes]
tempState.push({size:size,colors: [{color:color,stock,e.target.value}]})
setSizes(tempState)
}

最新更新