Dismissing a React Dropdown Menu by Clicking Outside its Container

Byte-Sized Series 1, Part 1

Ekohe is introducing Part 1 of the first of our new series: Byte-Sized.

Byte-Sized will include tips and snippets of code for specific features to help you learn the tools of the trade. The first series will be our suggestions on how to implement a React dropdown component and dismiss it.


Dropdown is a very common item-selection component. Unlike other selection components, however, it needs to be dismissed when clicking outside the component. We’ll address how React components handle events that occur outside itself and its parent container.

Let’s implement a primitive dropdown first:

// DropdownPage.js
import React, { Component } from 'react';
import './DropdownPage.css';
export default class DropdownPage extends Component {
constructor(props) {
super(props)
this.state = {
dropdownVisible: false
}
}
  toggleDropdown = (e) => {
this.setState(prevState => ({dropdownVisible: !prevState.dropdownVisible}))
}
  renderDropdownMenu() {
return (
<div className='dropdown-body'>
<div>
<input type='checkbox'/><span>option 1</span>
</div>
<div>
<input type='checkbox'/><span>option 2</span>
</div>
</div>
)
}
  render() {
return (
<div className='dropdown-container'>
<div className='dropdown-trigger'>
<button onClick={this.toggleDropdown}>
dropdown trigger
</button>
</div>
{
this.state.dropdownVisible &&
this.renderDropdownMenu()
}
</div>
)
}
}

The css file:

// DropdownPage.css
.dropdown-container {
/* must assign container position as relative */
position: relative;
width: 200px;
}
.dropdown-trigger {
padding: 10px 0px;
}
.dropdown-body {
position: absolute;
top: 100%;
width: 100%;
padding: 10px;
  background-color: white;
box-shadow: 1px 1px 1px 1px #888888;
  z-index: 2;
}

Notice the .dropdown-container position must be relative while the .dropdown-body position must be absolute so that the dropdown menu will always be visible relative to the dropdown container.

Here is the result:

In the next few days, we’ll introduce the requirement of dismissing the dropdown when clicking outside of the container and explore various options to tackle this new requirement. Stay-tuned!