I’m developing a web app feature where the City dropdown values should filter based on the selected Province. The problem is that when a user selects a Province, the City dropdown jumps to the first city of that province, but still displays all cities, including those from other provinces. I want the City dropdown to only show cities belonging to the selected province. Check out the live codesandbox here. Filtering logic is in /src/components/shared/header > Header.tsx.
Header component (attempted filtering logic lives here):
export const Header = ({ data, isLoading, error }: HeaderProps) => {
...
// Bring in global state
const {
provinceDropdownFilter,
cityDropdownFilter,
} = useFilterStore();
const filteredData = data.map((group) => group.equipments).flat();
...
const handleDropdownFilterProvince = (
e: React.ChangeEvent<HTMLSelectElement>
) => {
useFilterStore.setState({ provinceDropdownFilter: e.target.value });
// Filter the data based on the selected province
const filteredCities = filteredData
.filter((item) => item.state === e.target.value)
.map((item) => item.city);
// Set the filtered city dropdown options
useFilterStore.setState({ cityDropdownFilter: filteredCities[0] || "" });
};
const handleDropdownFilterCity = (
e: React.ChangeEvent<HTMLSelectElement>
) => {
useFilterStore.setState({ cityDropdownFilter: e.target.value });
// Filter the data based on the selected city
const filteredProvinces = filteredData
.filter((item) => item.city === e.target.value)
.map((item) => item.state);
// Set the filtered province dropdown options
useFilterStore.setState({
provinceDropdownFilter: filteredProvinces[0] || "",
});
};
...
return (
<>
...
<Dropdown
data={data}
value={provinceDropdownFilter}
onChange={handleDropdownFilterProvince}
filterType="state"
/>
<Dropdown
data={data}
value={cityDropdownFilter}
onChange={handleDropdownFilterCity}
filterType="city"
/>
...
</>
);
};
Dropdown component:
export const Dropdown: React.FC<DropdownProps> = ({
data,
onChange,
value,
filterType,
}) => {
...
// Map over the parent array as it has nested children arrays with all data containing.
// Combine all chidren into one combined array
const filteredData = data.map((group) => group.equipments).flat();
// Filter the data based on the filterType
const filteredOptions = filteredData.filter((i) => {
if (filterType === "manufacturer") {
return i.manufacturer;
}
if (filterType === "state") {
return i.state;
}
if (filterType === "city") {
return i.city;
}
return false;
});
...
return (
<>
<Select
aria-label="Select"
placeholder={getCustomPlaceholder(filterType) as string}
value={value}
onChange={handleFilters}
>
{Array.from(uniqueValues)
.sort()
.map((value) => (
<option key={value} value={value}>
{value}
</option>
))}
</Select>
</>
);
};