You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>
    );
};

关键修改说明

  1. 添加groupedOptions计算:通过useMemo根据选中的下拉框数量,将KPI_OPTIONS分割成近似均匀的分组,比如5个选项分3个下拉框时,分组为['ABC','DEF']、['GHI','JKL']、['MNO']
  2. 动态下拉框选项渲染:每个下拉框只渲染groupedOptions[index]对应的选项,不再显示全部KPI
  3. 选中状态同步:切换下拉框数量时,自动清空超出数量的选中值,以及不在新分组内的无效选中值
  4. 提交时过滤无效值:handleCreate中只传递当前选中数量内的有效选项

内容的提问来源于stack exchange,提问作者stackUser67

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 22:29:54