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
相关产品推荐
相关产品推荐

