React中如何实现选项在动态生成下拉框中均匀分配?
问题分析与解决方案
你当前的代码遗漏了KPI_OPTIONS的分组分配逻辑,所有动态生成的下拉框都显示完整的KPI选项列表,没有实现均匀/近似均匀分配的核心逻辑。
需要补充的关键逻辑
- 根据选中的下拉框数量,将KPI_OPTIONS分割为对应数量的分组,保证每组数量尽可能均匀
- 让每个动态下拉框只渲染分配给它的那组选项
- 同步维护选中选项的状态,避免切换下拉框数量时出现无效选中值
修改后的代码实现
const KPI_OPTIONS = [ "ABC", 'DEF', 'GHI', 'JKL', 'MNO' ]; const MAX_DROPDOWNS = 4; const CustomAddModal = ({ open, onClose, createHandler, onOptionsSelected }) => { const [selectedDropdownCount, setSelectedDropdownCount] = useState(''); const [dynamicDropdowns, setDynamicDropdowns] = useState([]); const [selectedOptions, setSelectedOptions] = useState(Array.from({ length: MAX_DROPDOWNS }, () => '')); // 根据选中的下拉框数量,计算均匀分组后的选项 const groupedOptions = useMemo(() => { if (!selectedDropdownCount) return []; const dropdownCount = parseInt(selectedDropdownCount); const baseCount = Math.floor(KPI_OPTIONS.length / dropdownCount); const remainder = KPI_OPTIONS.length % dropdownCount; const groups = []; let currentIndex = 0; for (let i = 0; i < dropdownCount; i++) { // 前remainder个下拉框多分配1个选项,保证近似均匀 const groupSize = baseCount + (i < remainder ? 1 : 0); groups.push(KPI_OPTIONS.slice(currentIndex, currentIndex + groupSize)); currentIndex += groupSize; } return groups; }, [selectedDropdownCount]); console.log(selectedOptions); const handleCreate = () => { // 过滤掉空值和超过当前下拉框数量的选项 const validSelected = selectedOptions.slice(0, parseInt(selectedDropdownCount)).filter(Boolean); onOptionsSelected(validSelected); createHandler(); setSelectedDropdownCount(''); onClose(); }; const generateDynamicDropdowns = (count) => { const newDropdowns = Array.from({ length: parseInt(count) }, (_, index) => index + 1); setDynamicDropdowns(newDropdowns); }; const handleOptionChange = (index, value) => { const newSelectedOptions = [...selectedOptions]; newSelectedOptions[index] = value; setSelectedOptions(newSelectedOptions); }; useEffect(() => { generateDynamicDropdowns(selectedDropdownCount); // 切换下拉框数量时,重置选中状态(清除无效选中值) const dropdownCount = parseInt(selectedDropdownCount) || 0; setSelectedOptions(prev => { const updated = [...prev]; for (let i = 0; i < MAX_DROPDOWNS; i++) { if (i >= dropdownCount) { updated[i] = ''; } else if (!groupedOptions[i]?.includes(updated[i])) { updated[i] = ''; } } return updated; }); }, [selectedDropdownCount, groupedOptions]); return ( <Modal open={open} closeAfterTransition > <Fade in={open}> <div style={{ ...modalStyle, width: '750px' }}> <IconButton style={{ position: 'absolute', top: '10px', right: '10px', color: COLOR_WHITE }} onClick={onClose}> <CloseIcon /> </IconButton> <div style={{ color: COLOR_WHITE, textAlign: 'center' }}>Custom</div> <div style={{ color: COLOR_WHITE }}>KPIs</div> <div className="dropdown-container" style={dropdownContainerStyle}> <Select sx={selectStyle} MenuProps={menuProps} value={selectedDropdownCount} onChange={(e) => setSelectedDropdownCount(e.target.value)} > <MenuItem sx={menuItemStyle} value="null">Select Option</MenuItem> <MenuItem sx={menuItemStyle} value="1">1</MenuItem> <MenuItem sx={menuItemStyle} value="2">2</MenuItem> <MenuItem sx={menuItemStyle} value="3">3</MenuItem> <MenuItem sx={menuItemStyle} value="4">4</MenuItem> </Select> {/* 渲染分配了对应分组选项的下拉框 */} {dynamicDropdowns.map((dropdown, index) => ( <Select key={index} sx={selectStyle} MenuProps={menuProps} value={selectedOptions[index]} onChange={(e) => handleOptionChange(index, e.target.value)} > <MenuItem sx={menuItemStyle} value=""> Select Option </MenuItem> {groupedOptions[index]?.map((option, optionIndex) => ( <MenuItem key={optionIndex} sx={menuItemStyle} value={option}> {option} </MenuItem> ))} </Select> ))} </div> <Button style={buttonStyle} onClick={handleCreate} variant="contained"> Create </Button> </div> </Fade> </Modal> ); };
关键修改说明
- 添加
groupedOptions计算:通过useMemo根据选中的下拉框数量,将KPI_OPTIONS分割成近似均匀的分组,比如5个选项分3个下拉框时,分组为['ABC','DEF']、['GHI','JKL']、['MNO'] - 动态下拉框选项渲染:每个下拉框只渲染
groupedOptions[index]对应的选项,不再显示全部KPI - 选中状态同步:切换下拉框数量时,自动清空超出数量的选中值,以及不在新分组内的无效选中值
- 提交时过滤无效值:
handleCreate中只传递当前选中数量内的有效选项
内容的提问来源于stack exchange,提问作者stackUser67
相关产品推荐
相关产品推荐

