I am developing an ecommerce store having search input and the result is showing as dropdown. Now searching and the search result showing is working. Now I want to close the dropdown on outside click of dropdown. Please check the below code,
const dispatch = useDispatch();
const [toggleSearch, setToggleSearch] = useState(false);
const {trending, searched} = useSelector(state => state.search);
function trendingSearch(e) {
setToggleSearch(true);
dispatch(fetchtrending());
}
function startSearch(e) {
let q = e.target.value;
dispatch(fetchsearch(q));
setToggleSearch(true);
}
<div className="col-12 col-md-6 col-lg-7 mt-3 mb-3 mt-md-0 mb-md-0">
<div className="search-box">
<div className="search-inner">
<input type="text" name="q" placeholder="Search for products, brands and much more" onFocus={(e) => trendingSearch(e)} onChange={(e) => startSearch(e)} />
<button><FontAwesomeIcon icon={faSearch}/></button>
</div>
<div className={toggleSearch ? "search-result" : "search-result d-none"}>
<ul>
{searched !== null && searched.data.length > 0 &&
searched.data.map((search, index) => (
<li key={index}><Link href={"/product/"+search.search_slug+"?pid="+search.search_pid}><a>{search.search_name}</a></Link></li>
))
}
</ul>
</div>
</div>
</div>
I have tried using onBlur
for input
. But the problem is I can't click links inside search result dropdown.
How to achieve closing dropdown only on click outside the the dropdown.
I am developing an ecommerce store having search input and the result is showing as dropdown. Now searching and the search result showing is working. Now I want to close the dropdown on outside click of dropdown. Please check the below code,
const dispatch = useDispatch();
const [toggleSearch, setToggleSearch] = useState(false);
const {trending, searched} = useSelector(state => state.search);
function trendingSearch(e) {
setToggleSearch(true);
dispatch(fetchtrending());
}
function startSearch(e) {
let q = e.target.value;
dispatch(fetchsearch(q));
setToggleSearch(true);
}
<div className="col-12 col-md-6 col-lg-7 mt-3 mb-3 mt-md-0 mb-md-0">
<div className="search-box">
<div className="search-inner">
<input type="text" name="q" placeholder="Search for products, brands and much more" onFocus={(e) => trendingSearch(e)} onChange={(e) => startSearch(e)} />
<button><FontAwesomeIcon icon={faSearch}/></button>
</div>
<div className={toggleSearch ? "search-result" : "search-result d-none"}>
<ul>
{searched !== null && searched.data.length > 0 &&
searched.data.map((search, index) => (
<li key={index}><Link href={"/product/"+search.search_slug+"?pid="+search.search_pid}><a>{search.search_name}</a></Link></li>
))
}
</ul>
</div>
</div>
</div>
I have tried using onBlur
for input
. But the problem is I can't click links inside search result dropdown.
How to achieve closing dropdown only on click outside the the dropdown.
Share Improve this question edited Jul 25, 2020 at 9:40 Jithin Varghese asked Jul 25, 2020 at 9:21 Jithin VargheseJithin Varghese 2,2284 gold badges31 silver badges61 bronze badges1 Answer
Reset to default 21You can add a click event listener (when the dropdown is opened) to either a backdrop element or the window itself to detect a click outside of the dropdown. Below is an implementation that I check if the click dropdown element contains the event.target
.
const { useState, useEffect, useRef } = React;
function App() {
const [showDropdown, setShowDropdown] = useState(false);
// create a React ref for the dropdown element
const dropdown = useRef(null);
useEffect(() => {
// only add the event listener when the dropdown is opened
if (!showDropdown) return;
function handleClick(event) {
if (dropdown.current && !dropdown.current.contains(event.target)) {
setShowDropdown(false);
}
}
window.addEventListener("click", handleClick);
// clean up
return () => window.removeEventListener("click", handleClick);
}, [showDropdown]);
return (
<div className="App">
<button onClick={() => setShowDropdown(b => !b)}>Toggle Dropdown</button>
{showDropdown && (
<div
ref={dropdown}
style={{ width: 100, height: 100, backgroundColor: "#bada55" }}
/>
)}
</div>
);
}
ReactDOM.render(<App />, document.getElementById("App"));
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<div id="App"></div>