React中如何去除数组对象的重复属性值且不破坏原有数量计算功能
解决方法
你出现重复选项的核心原因是直接遍历了完整的SKU属性数组,每个SKU都会对应输出一次颜色、尺寸选项,自然会重复。只需要先对属性值做去重预处理,再调整少量状态和交互逻辑即可,完全不会破坏原有的库存计算需求。
具体修改点:
- 提前从原始属性数组中提取去重后的颜色、尺寸列表,用于渲染单选框
- 新增两个状态存储当前选中的颜色、尺寸,库存可以根据选中的属性实时计算
- 调整单选框的渲染逻辑,绑定checked状态提升使用体验
- 调整属性变更后的库存计算逻辑,适配新的状态结构
修改后完整可运行代码:
import React, { useState, useMemo } from "react"; export default function ControlledRadios() { const data = [ { id: 1, name: "Product A", attributes: [ { id: 1, color: "Red", size: "Small", qty: 200 }, { id: 2, color: "Red", size: "Medium", qty: 100 }, { id: 3, color: "Red", size: "Large", qty: 300 }, { id: 4, color: "Yellow", size: "Small", qty: 200 }, { id: 5, color: "Yellow", size: "Medium", qty: 100 }, { id: 6, color: "Yellow", size: "Large", qty: 300 }, ], }, ]; // 预处理去重颜色、尺寸列表 const attributes = data[0].attributes; const uniqueColors = useMemo(() => [...new Set(attributes.map(item => item.color))], [attributes]); const uniqueSizes = useMemo(() => [...new Set(attributes.map(item => item.size))], [attributes]); // 存储选中的颜色、尺寸 const [selectedColor, setSelectedColor] = useState(null); const [selectedSize, setSelectedSize] = useState(null); // 实时计算对应库存 const qty = useMemo(() => { // 都没选返回总库存 if (!selectedColor && !selectedSize) { return attributes.reduce((sum, item) => sum + item.qty, 0); } // 只选了颜色返回该颜色总库存 if (selectedColor && !selectedSize) { return attributes.filter(item => item.color === selectedColor).reduce((sum, item) => sum + item.qty, 0); } // 都选了返回对应组合的库存 const target = attributes.find(item => item.color === selectedColor && item.size === selectedSize); return target ? target.qty : 0; }, [attributes, selectedColor, selectedSize]); const handleChange = (event) => { const { name, value } = event.target; if (name === "schedule-weekly-option-color") { setSelectedColor(value); } else { setSelectedSize(value); } }; return ( <> <h1>Quantity: {qty}</h1> <fieldset onChange={handleChange}> <h3>Color:</h3> {uniqueColors.map(color => ( <label key={color}> <input type="radio" name="schedule-weekly-option-color" value={color} checked={selectedColor === color} /> {color} </label> ))} <h3>Size:</h3> {uniqueSizes.map(size => ( <label key={size}> <input type="radio" name="schedule-weekly-option-size" value={size} checked={selectedSize === size} disabled={!selectedColor} // 可选:没选颜色的时候禁止选尺寸,不需要可删除 /> {size} </label> ))} </fieldset> </> ); }
效果说明:
修改后颜色只会展示Red、Yellow两个选项,尺寸只会展示Small、Medium、Large三个选项,完全没有重复。选中颜色时自动计算该颜色总库存,选中尺寸后自动计算对应组合的精确库存,和你原来的功能需求完全一致。
内容的提问来源于stack exchange,提问作者Mohammad Khan
相关产品推荐
相关产品推荐

