[英]React JS close dropdown using onBlur function
我在 React Js 上做了一個下拉列表。 我希望使用onBlur
function 在外部單擊時關閉下拉菜單。 這里的問題是,當單擊下拉選項時它也會關閉,並且不會執行附加到該選項的 function。 我想向onBlur
function 添加一個條件,它將檢查單擊的區域是在下拉列表內部還是外部並采取相應措施,但我不確定如何檢查。
我試過document.activeElement
,但那是選擇整個body
元素。
這是我的代碼沙盒鏈接: https://codesandbox.io/s/intelligent-tdd-zq4qcr?file=/src/App.js:938-941
這是 function 我需要幫助:
const close = (event) => {
// Help me with this function please
// I need to wrap this function in a condition that checks
// if the click was outside the dropdown
let dropdown = event.target.nextSibling;
// If I comment the lines below,
// it updates the number, but doesn't close the dropdown
if (dropdown?.classList.contains("display")) {
dropdown.classList.remove("display");
setOption("");
}
};
我正在添加一個 class 屬性display: unset
單擊下拉按鈕時未設置。 默認情況下,顯示設置為none
。
編輯:我的原始項目中這些下拉列表的數量是可變的。 它們可能是兩個,也可能是 10 個,具體取決於用戶。 所以我不能在 state 中維護它,需要使用 JavaScript 來跟蹤單擊了哪個下拉菜單。
您可以存儲打開的 state 並有條件地添加顯示 class。 要檢測 div 外部的點擊,您可以將 ref 傳遞給包裝器 div 並使用自定義掛鈎。
請注意,一般情況下,您應該避免直接操作 dom,如果您覺得必須這樣做,這很可能意味着您應該重新審視您的方法。
function useOnClickOutside(ref, cb) {
useEffect(() => {
function handleClickOutside(event) {
if (ref.current && !ref.current.contains(event.target)) {
cb();
}
}
// Bind the event listener
document.addEventListener("mousedown", handleClickOutside);
return () => {
// Unbind the event listener on clean up
document.removeEventListener("mousedown", handleClickOutside);
};
}, [ref, cb]);
}
function Dropdown({onSelect, values}) {
const [isOpen, setIsOpen] = useState(false);
const wrapperRef = useRef(null);
const close = () => {
setIsOpen(false);
};
useOnClickOutside(wrapperRef, close);
const toggle = () => {
setIsOpen(prev => !prev)
};
return (
<div className={`dropdown`} tabIndex={0}>
<button onClick={toggle}>•••</button>
<div ref={wrapperRef} style={{zIndex: 999}} className={`list ${isOpen ? 'display' : ''}`}>
<ul>
{values.map(v => <li
key={v}
onClick={() => {
onSelect(v)
setIsOpen(false)
}}>{"Option " + v}</li>)}
</ul>
</div>
</div>
)
}
export default function App() {
const [option, setOption] = useState(null);
return (
<div className="App">
<h2>Option: {option}</h2>
<p>
Dropdown should close when I click outside it
<br/>
Option Number should update
</p>
<Dropdown onSelect={setOption} values={[1, 2, 3]}/>
<Dropdown onSelect={setOption} values={[4, 5, 6]}/>
<Dropdown onSelect={setOption} values={[6, 7, 8]}/>
</div>
);
}
你有一個很好的開始,但是缺少一些東西。 不必自己添加/刪除 class,您可以為此創建一個 state 並讓 React 為您處理它。
此外,如果您在 div 上添加 onFocus 事件,您可以管理下拉菜單何時打開。
export default function App() {
const [option, setOption] = useState("");
const [isOpen, setIsOpen] = useState(false);
const close = () => {
setIsOpen(false);
}
const open = () => {
setIsOpen(true);
}
const selectValue = (event) => {
const value = event.target.value;
setOption(value);
close();
}
return (
<div className="App">
<h2>Option: {option}</h2>
<p>
Dropdown should close when I click outside it
<br />
Option Number should update
</p>
<div className="dropdown" tabIndex={0} onBlur={close} onFocus={open}>
<button onClick={open}>•••</button>
<div className={`list ${isOpen ? "display" : ""} `}>
<ul>
<li value={1} onClick={selectValue}>Option 1</li>
<li value={2} onClick={selectValue}>Option 2</li>
</ul>
</div>
</div>
</div>
);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.