A beginner-friendly React tutorial that walks you through creating a dropdown component by example. In this guide, youâll learn step by step how to build a dropdown in React. While HTML offers a built-in select element for similar functionality, React doesnât have such native primitives for dropdown components.
First, we need a HTML button element which will open (or close) a dropdown eventually. We are using an event handler in React to listen to the button âs click event and Reactâs useState Hook to manage the dropdownâs open state:
Since a dropdown features a menu that appears when the dropdown is clicked and disappears when closed, we will render this dropdown menu as a list of buttons.
Respectively to the open state, the dropdown menu is either displayed or not:
When clicking the dropdown button, you can see the list of buttons showing up. However, the menu pushes the âIs Openâ/âIs Closedâ text further to the bottom. In contrast, a real dropdown menu should float above the other HTML elements.
Therefore, the dropdown needs to be positioned absolutely to its container. While the last code snippet already introduced CSS classes in JSX, the next code snippet gives the dropdown its styles in React . We are using straight CSS for the dropdownâs menu, but feel free to use an alternative like Tailwind CSS:
The dropdownâs menu should float above the other HTML elements now. Whatâs missing are event handlers for each button in the dropdownâs menu. For each event handler, you can perform something specific like opening a dialog for example, while the handler also has to close the dropdown menu eventually:
Eventually you want to move all this logic for a dropdown component into a reusable React component . The new component comes with two slots (see component composition ). While one slot is for the trigger which opens/closes the dropdown, the other slot is for the buttons which are getting rendered in the dropdownâs menu. The new dropdown component also receives the open state of the dropdown:
Internally, the dropdown renders the trigger and the menu as a list .
However, there is still logic (e.g. open state) of the dropdown component sitting in its parent component. When instantiating multiple dropdown components, this will become repetitive logic in each parent component.
Therefore, the next step shows how to elegantly move all repetitive implementation details into the dropdown component by using Reactâs cloneElement API:
Reactâs cloneElement API allows us to attach props to the passed trigger element (here: opening/closing the dropdown, because it toggles the open state within the dropdown component).
Furthermore, the high-level API allows us to close the dropdown once a menu item in a dropdown is clicked while still preserving its native implementation (here: menuItem.props.onClick ).
The reusable dropdown component is finished. Whatâs missing is the implementation detail to close the dropdown if a user clicks outside of it. With the linked article though you should be able to get this done as well.