In this tutorial, I will show you how to filter a Dropdownlist based on another Dropdownlist in React. We would use the example of Product, Category and SubCategory to demonstrate this.
We would cover the following six steps
- Define the States
- Create the useEffect Hook to Fetch the Categories
- Create the useEffect Hook to Fetch the SubCategories
- Write the Categories <Select> and Handler
- Write the SubCategories <Select> and Handler
- Add Some Styling
1. Create the States
We would need states to hold the total categories list(categories, the complete subcategory list (allSubcategories) and the filtered sub-category list (filteredSubCategories)
These are defined as shown below:
const [categories, setCategories] = useState([]); const [allSubCategories, setAllSubCategories] = useState([]); const [filteredSubCategories, setFilteredSubCategories] = useState([]);
Also update the newProduct state to include categoryid and subcategoryid. This is shown below:
const [newProduct, setNewProduct] = useState({ title: '', summary: '', content: '', categoryid: '', subcategoryid: '', created_at: new Date().toISOString() // Set current datetime })
2. Create the useEffect Hook to Fetch Categories
We use the effect hook to load up the Categories when the application starts up.
useEffect(() => { axios.get('http://localhost:8081/categories').then((response) => { setCategories(response.data) }) .catch ((error) => { console.error('Error fetching categories:', error); }); }, []);
3. Create the useEffect Hook to Fetch SubCategories
We also want to load up the subCategories when the application starts up.
useEffect(() => { axios.get('http://localhost:8081/subCategories').then((response) => { setAllSubCategories(response.data); }) .catch((error) => { console.log('Error occurred fetching subcategories', error); }) }, []);
Update the Table: At this point you can update the table to include category and subcategory columns
4. Write the Categories Select and Handler
We load the categories into the <select> for categories. We also set the value to newProduct.categoryid. Also not the the default selected item is the text “Choose..” whose value defaults to empty string.
<select id="categoryid" onChange={handleCategoryChange} value={newProduct.categoryid} > <option >Choose...</option> {categories.filter(c => c.title != null).map(category => ( <option key={category.id} value={category.id}> {category.title} </option> ))} </select>
Write the event handler (handleCategoryChange): When the category is selected we do the following
- obtain the value of the category that was selected
- update the categoryid of the newProduct
- filter the subCategories base on the categoryid
const handleCategoryChange = (event) => { const selectedCategoryId = event.target.value; setNewProduct({ ...newProduct, categoryid: selectedCategoryId, subcategoryid: '' // Reset subcategory when category changes }); // Filter the subcategories based on the selected category const filteredSubCategories = allSubCategories.filter( (subCategory) => subCategory.categoryid === Number(selectedCategoryId) ); setFilteredSubCategories(filteredSubCategories); // Update the filtered subcategories }
5. Write the SubCategories Select and Handler
<select id="subcategoryid" value={newProduct.subcategoryid} onChange={handleSubCategoryChange}> <option>Choose...</option> {filteredSubCategories.map(subCategory => ( <option key={subCategory.id} value={subCategory.id}> {subCategory.description} </option> ))} </select>
In the handler for subCategories select, we simply obtain the selected sub-categoryid and use it to update the subcategoryid field of the newProduct
const handleSubCategoryChange = (event) => { const selectedSubCategoryId = event.target.value; setNewProduct({ ...newProduct, subcategoryid: selectedSubCategoryId }); };
6. Add Some Styling to the Select
We add some style to the <select> using the sx prop
style={{ width: '100%', // Makes it full width padding: '8px', // Adds padding for better UI borderRadius: '4px', // Adds rounded corners border: '1px solid #ccc', // Adds a border marginBottom: '16px', // Adds margin at the bottom fontSize: '16px', // Sets a readable font size }}
Now you can start the application and enjoy!!