The React dropdown menu component is easy to create. Learning React to create UI components on your own is a very good exercise.
In this tutorial, we create a custom React component to show a dropdown. It displays a multi-level dropdown menu on the site header.
The dropdown menu is about showing a list of clickable menu links or selectable options on a webpage. Some of the utilities of a React dropdown menu component are listed as follows.
There are various ways to render a dropdown menu using React. It has a built-in component <Select>
to display a dropdown list. It can also import Bootstrap libraries to use <Dropdown>
components to display selectable options to the UI.
The menu options are dynamic, and they are from the database. The database can map the main and subcategory category relationships.
The steps to create a custom React dropdown menu are as follows.
This SQL has the menu table structure and data. Create a database and import this script to see the menu items on the UI when seeing the React component.
sql/dropdown.sql
-- Table structure for table `tbl_menu`
--
CREATE TABLE `tbl_menu` (
`id` int(11) NOT NULL,
`parent_id` int(11) DEFAULT NULL,
`name` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
--
-- Dumping data for table `tbl_menu`
--
INSERT INTO `tbl_menu` (`id`, `parent_id`, `name`) VALUES
(1, NULL, 'PHP Contact Form'),
(2, NULL, 'PHP Shopping Cart'),
(3, 1, ' Contact form in wordpress'),
(4, 1, 'Responsive Contact Form'),
(5, 2, 'JavaScript Shopping Cart'),
(6, 2, 'Bootstrap for Shopping Cart'),
(7, NULL, 'Payment Integration'),
(8, NULL, 'Authentication'),
(9, NULL, 'Tutorial'),
(10, 1, 'Contact Form in WordPress'),
(11, 1, 'Bootstrap Contact Form'),
(12, 2, 'Responsive Shopping Cart'),
(13, 2, 'Shopping Cart like Amazon');
This code uses Axios to proceed with the API fetch over a remote call.
Run the following npm command to use the Axios in your JavaScript server call.
npm install axios
It prepares the HTTP GET request to call the API endpoint. The server will return a data source object array with menu options. Then, this script filters the parent and child menu options.
The fetchDataFromAPI()
function is called in the useEffect()
callback. This callback prepares the data source for the dropdown component when mounted.
When creating a React Select cascade, we use componentDidMount()
to call AJAX on the component mount event.
src/Dropdown.js
(Part of the code to perform Axios fetch)
const fetchDataFromAPI = async () => {
try {
const response = await axios.get('http://example.com/api/get-menu-options.php');
const data = response.data;
setParentItems(data.filter(item => item.parent_id === null));
setChildItems(data.filter(item => item.parent_id !== null));
} catch (error) {
console.error('Error fetching data: ', error);
}
};
useEffect(() => {
fetchDataFromAPI();
}, []);
This PHP file is created as the API endpoint for the React dropdown menu script.
It connects the tbl_menu database and fetches data to form the menu hierarchy.
It evaluates the request method before executing the database operations.
api/get-menu-options.php
<?php
header("Access-Control-Allow-Origin: *");
// Establish MySQL database connection
$servername = "localhost"; // Replace with your MySQL server name
$username = "root"; // Replace with your MySQL username
$password = ""; // Replace with your MySQL password
$dbname = "dropdown"; // Replace with your database name
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// API endpoint to fetch dropdown data
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
// Fetch data from the database using prepared statement
$query = "SELECT * FROM tbl_menu";
$stmt = $conn->prepare($query);
$stmt->execute();
$result = $stmt->get_result();
$dropdownData = array();
while ($row = $result->fetch_assoc()) {
$dropdownData[] = $row;
}
// Prepare JSON response
echo json_encode($dropdownData);
}
?>
This script filters the parent menu from the data source. Then, it maps the parent array to filter out the child menu by the parent index. This filtering helps to map data for the multi-level React dropdown menu.
The filtered menu list is displayed by hovering over the corresponding parent menu item.
src/dropdown.js
const filteredChildItems = childItems.filter(item => item.parent_id === activeParentId);
const hasChildItems = filteredChildItems.length > 0;
return (
<div id='demo-content' className='phppot-container'>
<div className='textline'>
<div className='hoverlink'
onMouseEnter={handleLinkHover}
onMouseLeave={() => setShowParentContainer(false)}
>
<a className='menu' >
{linkText}
</a>
{showParentContainer && (
<div className='parent-container'>
{parentItems.map(parentItem => {
const hasChildren = childItems.some(childItem => childItem.parent_id === parentItem.id);
return (
<div
key={parentItem.id}
onMouseEnter={() => handleParentItemHover(parentItem.id)}
className={parentItem.id === activeParentId ? 'parent-item active' : 'parent-item'}
>
<p className={hasChildren ? 'has-children' : ''}>
{parentItem.name}
{hasChildren && <span className='triangle-arrow'>▸</span>}
</p>
</div>
);
})}
</div>
)}
{showParentContainer && activeParentId !== null && hasChildItems && (
<div className='child-container'
onMouseLeave={handleChildItemHover}
>
<div>
{filteredChildItems.map(childItem => (
<div key={childItem.id}>
<p>{childItem.name}</p>
</div>
))}
</div>
</div>
)}
</div>
<a className='menu' href='#'>Products</a>
<a className='menu' href='#'>Other Offers</a>
<a className='menu' href='#'>Contact</a>
</div>
</div>
);
};
export default Dropdown;
This code defines two state variables. Those are to set the active parent menu and the state of showing the parent dropdown menu.
Initially, all the parent dropdown menu elements will be set as false. On hovering the header link, the handleLinkHover()
listener sets the parent menu display state to true. At the same time, the currently active parent id will be updated on the useState.
On hovering the parent menu item, the handleParentItemHover
function is called. It shows the second level of categories in the level 2 dropdown menu.
src/dropdown.js
const handleLinkHover = () => {
setShowParentContainer(true);
setActiveParentId(null);
};
const handleParentItemHover = (parentId) => {
setShowParentContainer(true);
setActiveParentId(parentId);
};
const handleChildItemHover = () => {
setShowParentContainer(false);
};