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

React.js项目中Bootstrap下拉菜单无法关闭问题求助

问题

在React.js项目开发筛选器时,遇到react-bootstrap下拉菜单的两个问题:

  1. 点击按钮能展开下拉列表,但再次点击按钮或点击列表外部无法收起
  2. 导入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 &#8964;" 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 &#8964;">
                <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 &#8964;">
                <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 &#8964;">
                <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 &#8964;">
                <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 &#8964;"
  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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 03:15:39