如何捕获并重置多个React-Bootstrap <Form.Select>组件状态
问题描述
- 无法通过按钮清除所有
<Form.Select>下拉框的状态,也不清楚如何获取每个下拉框的选中值 - 当前所有下拉框共用同一个
selectValue状态,导致选中一个下拉框时其他所有下拉框都会被重置 - 清除按钮仅能重置单个状态,无法批量重置所有下拉框到初始空值
- 点击“Filter Issues”按钮时无法获取所有下拉框的选中值
解决方案
核心问题是所有下拉框共用了同一个状态变量,改成用对象存储每个下拉框的独立值,就能分别控制状态、实现批量重置和批量获取值的功能。
步骤1:重构状态变量
将单个selectValue替换为包含所有下拉框键名的对象,初始值均为空字符串:
const [filterValues, setFilterValues] = useState({ site: "", profile: "", type: "", status: "", category: "", subcategory: "" });
步骤2:修改下拉框的value与onChange
每个下拉框的value对应filterValues中的对应键,onChange时更新对象里的指定键值:
示例(Site下拉框):
<Form.Select name='site' value={filterValues.site} onChange={(e) => { setFilterValues(prev => ({ ...prev, site: e.target.value })); }} >
其他下拉框同理,将value改为filterValues.xxx,onChange时更新对应键。
Category下拉框需同时更新选中值和子分类列表,修改如下:
<Form.Select name='category' value={filterValues.category} onChange={(e) => { const categoryId = parseInt(e.target.value); // 更新子分类列表 let filterCategory = issueCategorySubCategory.SubCategory.filter( (item) => item.CategoryId === categoryId ); setStates(filterCategory); // 更新category选中值 setFilterValues(prev => ({ ...prev, category: e.target.value })); }} >
步骤3:实现批量清除功能
点击“Clear Filter”按钮时,重置filterValues为初始空对象,同时重置子分类列表:
<Button variant='danger' className='m-1' onClick={() => { setFilterValues({ site: "", profile: "", type: "", status: "", category: "", subcategory: "" }); setStates([]); }}>Clear Filter</Button>
步骤4:获取所有选中值
点击“Filter Issues”按钮时,直接使用filterValues对象即可拿到所有下拉框的选中值:
<Button variant='success' className='m-1' onClick={() => { // 此处可直接使用filterValues做筛选逻辑或提交 console.log("所有筛选参数:", filterValues); }}>Filter Issues</Button>
修改后的完整代码
function FilterIssues() { const [states, setStates] = useState([]); // 用对象存储每个下拉框的独立状态 const [filterValues, setFilterValues] = useState({ site: "", profile: "", type: "", status: "", category: "", subcategory: "" }); return ( <Card style={{ width: '50%', marginLeft: 'auto', marginRight: 'auto', marginTop: '0.5%' }} border='secondary'> <Card.Body style={{ paddingTop: '2%', paddingBottom: '2%' }}><h4>Filter Issues</h4> <Form> <Row className="mb-4"> <Form.Group as={Col} controlId="formGridOwner"> Site <Form.Select name='site' value={filterValues.site} onChange={(e) => { setFilterValues(prev => ({ ...prev, site: e.target.value })); }} > <option value="">Choose...</option> {walkSiteProfileType.Site.map((item) => { return ( <option value={item} key={item}>{item}</option> ); })}; </Form.Select> </Form.Group> <Form.Group as={Col} controlId="formGridStatus"> Profile <Form.Select name='profile' value={filterValues.profile} onChange={(e) => { setFilterValues(prev => ({ ...prev, profile: e.target.value })); }} > <option value="">Choose...</option> {walkSiteProfileType.Profile.map((item) => { return ( <option value={item} key={item}>{item}</option> ); })}; </Form.Select> </Form.Group> <Form.Group as={Col} controlId="formGridStatus"> Type <Form.Select name='type' value={filterValues.type} onChange={(e) => { setFilterValues(prev => ({ ...prev, type: e.target.value })); }} > <option value="">Choose...</option> {walkSiteProfileType.Type.map((item) => { return ( <option value={item} key={item}>{item}</option> ); })}; </Form.Select> </Form.Group> </Row> <Row className="mb-4"> <Form.Group as={Col} controlId="formGridOwner"> Status <Form.Select name='status' value={filterValues.status} onChange={(e) => { setFilterValues(prev => ({ ...prev, status: e.target.value })); }} > <option value="">Choose...</option> {issueCategorySubCategory.Status.map((item) => { return ( <option value={item} key={item}>{item}</option> ); })}; </Form.Select> </Form.Group> <Form.Group as={Col} controlId="formGridCategory"> Category{" "} <Form.Select name='category' value={filterValues.category} onChange={(e) => { const categoryId = parseInt(e.target.value); let filterCategory = issueCategorySubCategory.SubCategory.filter( (item) => item.CategoryId === categoryId ); setStates(filterCategory); setFilterValues(prev => ({ ...prev, category: e.target.value })); }} > <option value="">Choose...</option> {issueCategorySubCategory.Category.map((item) => { return ( <option value={item.CategoryId} key={item.CategoryId}> {item.CategoryName} </option> ); })} </Form.Select> </Form.Group> <Form.Group as={Col} controlId="formGridSubCategory"> Subcategory{" "} <Form.Select name='subcategory' value={filterValues.subcategory} onChange={(e) => { setFilterValues(prev => ({ ...prev, subcategory: e.target.value })); }} > <option value="">Choose...</option> {states.map((item) => { return ( <option value={item.SubId} key={item.SubId}> {item.name} </option> ); })} </Form.Select> </Form.Group> </Row> </Form> </Card.Body> <Card.Footer> <Button variant='success' className='m-1' onClick={() => { console.log("筛选参数:", filterValues); // 此处添加筛选逻辑 }}>Filter Issues</Button> <Button variant='danger' className='m-1' onClick={() => { setFilterValues({ site: "", profile: "", type: "", status: "", category: "", subcategory: "" }); setStates([]); }}>Clear Filter</Button> <AddNewIssueModal></AddNewIssueModal> </Card.Footer> </Card> ) }
额外优化
- 给所有
option添加key属性,符合React列表渲染规范 - 将Category下拉框的“Choose...”选项移到前面,保持和其他下拉框一致的顺序
内容的提问来源于stack exchange,提问作者Andrew McKenzie
相关产品推荐
相关产品推荐

