Posted by Kosal
Dropdowns are a feature common to many websites. It's very useful, as they make it easy to show additional data only when it is needed. Dropdown menus allow you to make a web app clean and intuitive.
In this article, we will cover 2 examples:
Within index.js
, we call the App component. We define this component in App.js
:
.menu {
position: relative;
float: left;
}
.dropdown {
position: absolute;
width: 200px;
border: 1px solid #ccc;
}
// In `App.js`
import { useState, useEffect, useRef } from "react";
import "./App.css";
function App() {
// Create a ref for the element to detect outside clicks
const ref = useRef();
// Our dropdown's state
const [isOpenDropdown, setOpenDropdown] = useState(false);
// Call hook passing in the ref and a function to call on outside click
useEffect(() => {
const handleClickOutside = (event) => {
// Do nothing if clicking ref's element or descendent elements
if (ref && !ref.current.contains(event.target) && isOpenDropdown) {
setOpenDropdown(false);
}
};
// When user click any place in document
document.addEventListener("click", handleClickOutside);
return () => {
// Clean it on rerender
document.removeEventListener("click", handleClickOutside);
};
}, [ref, isOpenDropdown, setOpenDropdown]);
return (
<div ref={ref} className="menu">
<button
type="button"
onClick={(e) => {
e.preventDefault();
setOpenDropdown(!isOpenDropdown);
}}
>
Open menu
</button>
{isOpenDropdown && (
<div className="dropdown">
<ul>
<li>Copy</li>
<li>Paste</li>
<li>Delete</li>
</ul>
</div>
)}
</div>
);
}
export default App;
// In `App.js`
import { Component, createRef } from "react";
import "./App.css";
class App extends Component {
// Create a ref for the element to detect outside clicks
ref = createRef();
// Our dropdown's state
state = {
isOpenDropdown: false,
};
constructor(props) {
super(props);
this.handleClickOutside = this.handleClickOutside.bind(this);
}
componentDidMount() {
// Call hook passing in the ref and a function to call on outside click
document.addEventListener("click", this.handleClickOutside);
}
componentWillUnmount() {
// Clean it on rerender
document.removeEventListener("click", this.handleClickOutside);
}
handleClickOutside(event) {
// Do nothing if clicking ref's element or descendent elements
const { isOpenDropdown } = this.state;
if (
this.ref &&
!this.ref.current.contains(event.target) &&
isOpenDropdown
) {
this.setState({ isOpenDropdown: false });
}
}
render() {
const { isOpenDropdown } = this.state;
return (
<div ref={this.ref} className="menu">
<button
type="button"
onClick={(e) => {
e.preventDefault();
this.setState({ isOpenDropdown: !isOpenDropdown });
}}
>
Open menu
</button>
{isOpenDropdown && (
<div className="dropdown">
<ul>
<li>Copy</li>
<li>Paste</li>
<li>Delete</li>
</ul>
</div>
)}
</div>
);
}
}
export default App;
Hope this article can help you.