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

React分组复选框单选功能实现方案问询

实现React复选框分组单选的解决方案

要实现同一分组内仅能勾选一个复选框,核心是给每个分组维护独立的选中状态,通过状态控制复选框的选中状态,点击时更新对应分组的选中项。具体修改步骤如下:

  • 添加状态管理每个分组的选中项
  • 给每个复选框设置checked属性,根据对应分组的选中值判断是否选中
  • 修改点击逻辑,更新对应分组的选中状态,同时触发原有的过滤逻辑

修改后的完整代码:

import React, { useState } from 'react';

const checkboxes = [
    {
        heading : 'Price',
        labels : [
            {
                label: 'Up to £39.99',
                filter: '0',
                filterLimit: '39.99',
            },
            {
                label: '£40 to £59.99',
                filter: '40',
                filterLimit: '59.99',
            },
            {   
                label: '£60 to £79.99',
                filter: '60',
                filterLimit: '79.99',
            },
            {
                label: '£80 to £99.99',
                filter: '80',
                filterLimit: '99.99',
            },
            {
                label: '£100 to £199.99',
                filter: '100',
                filterLimit: '199.99',
            },
        ],
    },
    {
        heading : 'Brand',
        labels : [
            {
                label: 'BrandA',
                filter : 'BrandA',
            },
            {
                label: 'BrandB',
                filter: 'BrandB',
            },
            {
                label: 'BrandC',
                filter: 'BrandC',
            },
            {
                label: 'BrandD',
                filter: 'BrandD',
            },
            {
                label: 'BrandE',
                filter: 'BrandE',
            },
        ],
    },
];

export default function Sidebar(props) {
    const isntDesktop = props.isntDesktop;
    const sidebar = props.sidebar;
    const setSidebar = props.setSidebar;
    const setLoading = props.setLoading;
    const setFilter = props.setFilter;
    const setFilterLimit = props.setFilterLimit;

    // 管理每个分组的选中状态
    const [selectedFilters, setSelectedFilters] = useState({
        Price: '',
        Brand: ''
    });

    const handleFilterClick = (groupHeading, label) => {
        setLoading(true);
        // 判断当前选项是否已选中,是则取消,否则选中
        const newSelectedValue = selectedFilters[groupHeading] === label.filter 
            ? '' 
            : label.filter;
        
        // 更新当前分组的选中状态
        setSelectedFilters(prev => ({
            ...prev,
            [groupHeading]: newSelectedValue
        }));

        // 触发父组件的过滤逻辑,取消选中时清空对应参数
        setFilter(newSelectedValue);
        setFilterLimit(newSelectedValue ? label.filterLimit : '');
    };

    return (
        <>
            {/* Overlay */}
            {sidebar && isntDesktop && (
                <div className="h-screen w-screen absolute top-0 right-0 bg-gray-500 opacity-60 backdrop-blur"></div>
            )}

            {/* Sidebar */}
            {sidebar && (
                <div className="lg:w-1/4 h-screen absolute right-0 top-0 z-10 lg:relative p-20 lg:px-5 lg:py-2 space-y-5 rounded bg-gray-100 lg:bg-gray-50">
                    {/* Close button */}
                    {isntDesktop && (
                        <svg 
                            xmlns="http://www.w3.org/2000/svg" 
                            fill="none" 
                            viewBox="0 0 24 24" 
                            stroke-width="1.5" 
                            stroke="currentColor" 
                            onClick={() => setSidebar(!sidebar)}
                            className="w-6 h-6 absolute right-5 top-5 cursor-pointer" 
                        >
                            <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
                        </svg>
                    )}

                    {/* Checkboxes */}
                    {checkboxes.map((checkbox, index) => {
                        return (
                            <div key={index}>
                                <h3 className="text-base text-gray-600 font-bold">{checkbox.heading}</h3>

                                {checkbox.labels.map((label, labelIndex) => {
                                    return (
                                        <div
                                            key={labelIndex}
                                            onClick={() => handleFilterClick(checkbox.heading, label)}
                                            className="mt-2.5"
                                        >
                                            <input 
                                                className="h-4 w-4 border border-gray-300 rounded-sm bg-white accent-sky-600 focus:outline-none transition duration-200 mt-1 align-top bg-no-repeat bg-center bg-contain float-left mr-2 cursor-pointer" 
                                                type="checkbox" 
                                                // 根据状态设置选中状态
                                                checked={selectedFilters[checkbox.heading] === label.filter}
                                            />
                                            <label className="inline-block text-gray-500">
                                                {label.label}
                                            </label>
                                        </div>
                                    )
                                })}
                                <hr className="border-gray-300" />
                            </div>
                        )
                    })}
                </div>
            )}
        </>
    )
}

关键修改点说明:

  • 状态管理:新增selectedFilters对象,分别记录Price和Brand分组的选中项,初始为空表示未选中任何选项
  • 选中状态控制:每个复选框的checked属性绑定对应分组的选中值,确保同一时间只有一个选项被勾选
  • 点击逻辑优化:提取handleFilterClick函数,统一处理点击事件,支持取消选中(再次点击已选中的选项会清空该分组的选中状态),同时同步更新父组件的过滤参数
  • 样式修正:把原代码中混用的class改为React规范的className

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 23:01:13