React.js项目中Bootstrap下拉菜单无法关闭问题求助
问题
在React.js项目开发筛选器时,遇到react-bootstrap下拉菜单的两个问题:
- 点击按钮能展开下拉列表,但再次点击按钮或点击列表外部无法收起
- 导入Bootstrap CSS可解决收起问题,但会破坏自定义样式,因此暂时注释了CSS导入
代码片段
React组件代码
import React, { useEffect, useState } from 'react'; // import '../bootstrap/css/bootstrap.css'; import "bootstrap/dist/js/bootstrap.min.js"; import Popper from 'popper.js'; import Dropdown from 'react-bootstrap/Dropdown'; import DropdownButton from 'react-bootstrap/DropdownButton'; import './Filterbar.css'; export default function Filterbar() { function handlePropertyTypeChange(event){ console.log(event.target.value); event = setPropteryType(event.target.value); }; function handlePriceRangeChange(event){ console.log(event.target.value); event = setPriceRange(event.target.value); }; function handleBedroomChange(event){ console.log(event.target.value); event = setBedroomQTY(event.target.value); }; function handleBathroomChange(event){ console.log(event.target.value); event = setBathroomQTY(event.target.value); }; function handleCityChange(event){ console.log(event.target.value); event = setCityChoice(event.target.value); }; const [propertyType, setPropteryType] = useState(''); const [priceRange, setPriceRange] = useState(''); const [BedroomQTY, setBedroomQTY] = useState(''); const [BathroomQTY, setBathroomQTY] = useState(''); const [cityChoice, setCityChoice] = useState(''); return ( <div className='FilterbarBody'> <DropdownButton type="button" id="dropdown-basic-button" title="Property Type ⌄" data-bs-toggle="dropdown" aria-expanded="false"> <Dropdown.Item value={0} name="Property Type" onChange={handlePropertyTypeChange} aria-labelledby="dropdown-basic-button">All</Dropdown.Item> <Dropdown.Item value={1} name="Property Type" onChange={handlePropertyTypeChange} aria-labelledby="dropdown-basic-button">Single Family Home</Dropdown.Item> <Dropdown.Item value={2} name="Property Type" onChange={handlePropertyTypeChange} aria-labelledby="dropdown-basic-button">Multi Family Home</Dropdown.Item> </DropdownButton> <DropdownButton id="dropdown-basic-button2" title="Price ⌄"> <Dropdown.Item value={0} name="Price Range" onChange={handlePriceRangeChange}>All</Dropdown.Item> <Dropdown.Item value={500} name="Price Range" onChange={handlePriceRangeChange}>500+</Dropdown.Item> <Dropdown.Item value={1000} name="Price Range" onChange={handlePriceRangeChange}>1,000+</Dropdown.Item> <Dropdown.Item value={1500} name="Price Range" onChange={handlePriceRangeChange}>1,500+</Dropdown.Item> <Dropdown.Item value={2000} name="Price Range" onChange={handlePriceRangeChange}>2,000+</Dropdown.Item> <Dropdown.Item value={2500} name="Price Range" onChange={handlePriceRangeChange}>2,500+</Dropdown.Item> <Dropdown.Item value={3000} name="Price Range" onChange={handlePriceRangeChange}>3,000+</Dropdown.Item> </DropdownButton> <DropdownButton id="dropdown-basic-button3" title="Bedroom ⌄"> <Dropdown.Item value={0} name="Bedroom" onChange={handleBedroomChange}>All</Dropdown.Item> <Dropdown.Item value={1} name="Bedroom" onChange={handleBedroomChange}>1+</Dropdown.Item> <Dropdown.Item value={2} name="Bedroom" onChange={handleBedroomChange}>2+</Dropdown.Item> <Dropdown.Item value={3} name="Bedroom" onChange={handleBedroomChange}>3+</Dropdown.Item> <Dropdown.Item value={4} name="Bedroom" onChange={handleBedroomChange}>4+</Dropdown.Item> <Dropdown.Item value={5} name="Bedroom" onChange={handleBedroomChange}>5+</Dropdown.Item> <Dropdown.Item value={6} name="Bedroom" onChange={handleBedroomChange}>6+</Dropdown.Item> </DropdownButton> <DropdownButton id="dropdown-basic-button4" title="Bathroom ⌄"> <Dropdown.Item value={0} name="Bathroom" onChange={handleBathroomChange}>All</Dropdown.Item> <Dropdown.Item value={1} name="Bathroom" onChange={handleBathroomChange}>1+</Dropdown.Item> <Dropdown.Item value={2} name="Bathroom" onChange={handleBathroomChange}>2+</Dropdown.Item> <Dropdown.Item value={3} name="Bathroom" onChange={handleBathroomChange}>3+</Dropdown.Item> <Dropdown.Item value={4} name="Bathroom" onChange={handleBathroomChange}>4+</Dropdown.Item> <Dropdown.Item value={5} name="Bathroom" onChange={handleBathroomChange}>5+</Dropdown.Item> <Dropdown.Item value={6} name="Bathroom" onChange={handleBathroomChange}>6+</Dropdown.Item> </DropdownButton> <DropdownButton id="dropdown-basic-button5" title="City ⌄"> <Dropdown.Item value={""} name="City" onChange={handleCityChange}>All</Dropdown.Item> <Dropdown.Item value={"Cape Coral"} name="City" onChange={handleCityChange}>Cape Coral</Dropdown.Item> <Dropdown.Item value={"Fort Myers"} name="City" onChange={handleCityChange}>Fort Myers</Dropdown.Item> <Dropdown.Item value={"Lehigh Acres"} name="City" onChange={handleCityChange}>Lehigh Acres</Dropdown.Item> </DropdownButton> </div> ) }
自定义样式代码
.FilterbarBody { display: block; background-color:gainsboro; width: 53em; height: 2.50em; margin-top: 1em; margin-left: auto; margin-right: auto; margin-bottom: 1.50em; border: .13em solid #808080; font-style: 'sans-serif'; font-size: 1.25em; } .FilterbarBody > .dropdown { display:inline-block; margin-top: auto; margin-bottom: auto; margin-left: auto; margin-right: auto; text-decoration: none; font-style: 'sans-serif'; } .FilterbarBody > .dropdown > button { display: block; margin-left: 1.23em; margin-right: 1.23em; text-decoration: none; background-color: rgba(250, 235, 215, 0); padding: .75em 1.75em; font-size: 1em; list-style: none; border: none; border-radius: .50em; } .FilterbarBody > .dropdown > button:hover { background-color:rgba(250, 240, 230, 0); color: red; } .dropdown-item { display:block; text-decoration: none; color: white; background-color: black; border-bottom: 0.010em solid linen; font-style: 'sans-serif'; font-weight: .25em; padding: 1em 1.75em; } .dropdown-item:hover { background-color: linen; color: red; }
解决方案
一、修复下拉菜单无法收起的问题
react-bootstrap的下拉组件依赖Bootstrap CSS中的show类来控制展开/收起状态,不想全量导入的话,可以用以下两种方法解决:
方法1:手动管理下拉状态
利用组件自身的show属性和onToggle回调,自己控制每个下拉的展开/收起,同时添加点击外部关闭的逻辑:
// 在组件内添加每个下拉的状态变量 const [showPropertyType, setShowPropertyType] = useState(false); const [showPrice, setShowPrice] = useState(false); const [showBedroom, setShowBedroom] = useState(false); const [showBathroom, setShowBathroom] = useState(false); const [showCity, setShowCity] = useState(false); // 添加点击外部关闭下拉的逻辑 useEffect(() => { const handleClickOutside = (e) => { const dropdowns = document.querySelectorAll('.dropdown'); dropdowns.forEach(dropdown => { if (!dropdown.contains(e.target)) { setShowPropertyType(false); setShowPrice(false); setShowBedroom(false); setShowBathroom(false); setShowCity(false); } }); }; document.addEventListener('mousedown', handleClickOutside); return () => document.removeEventListener('mousedown', handleClickOutside); }, []); // 修改DropdownButton,绑定状态和回调 <DropdownButton id="dropdown-basic-button" title="Property Type ⌄" show={showPropertyType} onToggle={(isOpen) => setShowPropertyType(isOpen)} > {/* 下拉项保持不变 */} </DropdownButton>
方法2:导入下拉核心样式
把Bootstrap中控制下拉显示的核心样式提取出来,加到你的自定义CSS文件中,避免全量导入:
/* 下拉核心控制样式 */ .dropdown { position: relative; } .dropdown-menu { position: absolute; top: 100%; left: 0; z-index: 1000; display: none; } .dropdown-menu.show { display: block; }
二、避免自定义样式被覆盖
如果选择导入部分Bootstrap样式,通过以下方式提升自定义样式优先级:
- 使用更具体的选择器,比如用
.FilterbarBody .dropdown-item代替.dropdown-item - 确保自定义样式文件在Bootstrap部分样式之后导入
- 紧急情况下可以给样式添加
!important(不推荐频繁使用)
额外优化:下拉项事件不生效问题
react-bootstrap的Dropdown.Item默认不触发onChange,建议改成onClick事件,同时选择后自动关闭下拉:
<Dropdown.Item onClick={() => { setPropteryType(0); setShowPropertyType(false); }} > All </Dropdown.Item>
内容的提问来源于stack exchange,提问作者JonD
相关产品推荐
相关产品推荐

