![](/img/trans.png)
[英]React Closing dropdown menu on selecting a list item or clicking outside the component
[英]Closing a list item dropdown on selecting an item or clicking outside it
我在我的 react js 項目中創建了一個下拉列表,其中包含列表項(下拉項在此處由 ul 和 li 標簽顯示)。
我面臨的問題是,在選擇任何項目時,狀態值會發生變化,但下拉列表不會關閉,當我單擊它之外的任何地方時,它不會關閉。 請幫幫我,這是同一個 repo 的有效代碼和框 url
我也在下面分享代碼。
應用程序.js
import React, { Component, useState } from "react";
import Dropdown from "./dropdown";
import "./dropdown.css";
const App = () => {
const [value, setValue] = useState("");
const [showDropdown, setShowDropdown] = useState(false);
const selectedValue = (value) => {
console.log(value);
setValue(value);
};
const onSelectItem = () => {
console.log("12");
setShowDropdown(false);
};
return (
<section className="shadow-border" id="FlightsForm">
<div className="top-sec d-flex">
<div className="left-side">
<span
className="custm-dropdown"
onClick={() => setShowDropdown(true)}
>
<span style={{ backgroundColor: "grey", color: "white" }}>
{value.tripType}
</span>
<span className="dropdown-icon"> </span>
<Dropdown
selectedValue={selectedValue}
onSelectItem={onSelectItem}
showDropdown={showDropdown}
/>
</span>
</div>
</div>
</section>
);
};
export default App;
下拉菜單
import React from "react";
import { useState, useEffect } from "react";
const TripTypeDropdown = (props) => {
const [values, setValues] = useState([
{ tripType: "One Way", value: 1 },
{ tripType: "Return", value: 2 },
{ tripType: "Multi- City", value: 3 },
]);
const [selectedItem, setSelectedItem] = useState({
tripType: "One Way",
value: 1,
});
useEffect(() => {
props.selectedValue(selectedItem);
console.log(selectedItem);
}, [selectedItem]);
const selectItemFromList = (index) => {
const itemSelected = values[index];
setSelectedItem(itemSelected);
props.onSelectItem();
};
const getActiveClassName = (item) => {
if (selectedItem) {
if (item.tripType == selectedItem.tripType) return "active";
else return "";
}
} ;
return (
<React.Fragment>
<div
className={`dropdown-modal sm-modal ripple trip-type-dropdown`}
style={{ display: `${props.showDropdown ? "block" : "none"}` }}
>
<ul>
{console.log(values)}
{values.map((item, index) => (
<li
className={getActiveClassName(item)}
onClick={() => selectItemFromList(index)}
key={index}
style={{backgroundColor:'yellow',border:"1px solid black",listStyle:"none"}}
>
{item.tripType}
</li>
))}
</ul>
</div>
</React.Fragment>
);
};
export default TripTypeDropdown;
您需要停止從下拉組件到其父 span 元素的 click 事件冒泡。 單擊時,您需要傳遞事件參數並調用事件對象的stopPropagation
函數
下拉菜單
const selectItemFromList = (e,index) => {
e.stopPropagation();
...
<li
className={getActiveClassName(item)}
onClick={(e) => selectItemFromList(e,index)}
key={index}
還添加了外部點擊的代碼。
const ref = useRef();
...
useEffect(() => {
document.addEventListener("click", handleDropdownClick);
}, [ref]);
const handleDropdownClick = (e) => {
e.stopPropagation();
if (ref.current && ref.current.contains(e.target)) {
setShowDropdown(true);
} else {
setShowDropdown(false);
}
};
...
<span
ref={ref}
className="custm-dropdown"
onClick={handleDropdownClick}
>
您應該停止將單擊事件從列表項傳播到外部跨度,這會阻止從父項再次關閉下拉列表的任何嘗試。
const selectItemFromList = (index) => (e) => {
e.stopPropagation();
const itemSelected = values[index];
setSelectedItem(itemSelected);
props.onSelectItem();
};
...
<li
key={index}
...
onClick={selectItemFromList(index)}
...
>
{item.tripType}
</li>
要處理外部點擊,您將 React ref 附加到下拉 div 並使用useEffect
鈎子將onClick
事件偵聽器添加到 widow 對象,並檢查onClick
的事件目標是否不包含在下拉 div 中。
useEffect(() => {
const outsideClickHandler = (e) => {
if (props.showDropdown && !outsideRef.current?.contains(e.target)) {
props.onSelectItem(false);
}
};
window.addEventListener("click", outsideClickHandler);
return () => window.removeEventListener("click", outsideClickHandler);
}, [props]);
...
<div
ref={outsideRef}
...
>
...
</div>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.