React项目中如何根据下拉框选中的省份筛选城市?
问题:城市下拉框未根据选中省份筛选
我正在开发一个Web应用,需要实现城市下拉框选项根据选中省份动态筛选的功能,但目前选择省份或城市时完全没有筛选效果。
以下是我尝试过但无效的代码实现:
Header组件(筛选逻辑写在此处)
export const Header = ({ data, isLoading, error }: HeaderProps) => { ... // 引入全局状态 const { provinceDropdownFilter, cityDropdownFilter, } = useFilterStore(); const filteredData = data.map((group) => group.equipments).flat(); ... const handleDropdownFilterProvince = ( e: React.ChangeEvent<HTMLSelectElement> ) => { useFilterStore.setState({ provinceDropdownFilter: e.target.value }); // 根据选中的省份筛选数据 const filteredCitiesSet = new Set<string>( filteredData .filter((item) => item.state === e.target.value) .map((item) => item.city) ); const filteredCities = Array.from(filteredCitiesSet); useFilterStore.setState({ filteredCities: filteredCities }); console.log("handle province dropdown cities", filteredCities); }; const handleDropdownFilterCity = ( e: React.ChangeEvent<HTMLSelectElement> ) => { useFilterStore.setState({ cityDropdownFilter: e.target.value }); }; ... return ( <> ... <Dropdown data={data} value={manufacturerDropdownFilter} onChange={handleDropdownFilterManufacturer} filterType="manufacturer" /> <Dropdown data={data} value={provinceDropdownFilter} onChange={handleDropdownFilterProvince} filterType="state" /> <Dropdown data={data} value={cityDropdownFilter} onChange={handleDropdownFilterCity} filterType="city" /> ... </> ); };
Dropdown组件
export const Dropdown: React.FC<DropdownProps> = ({ data, onChange, value, filterType, }) => { ... const filteredData = data.map((group) => group.equipments).flat(); // 根据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> </> ); };
Zustand状态仓库
const useFilterStore = create<FilterState>( zukeeper((set: any) => ({ ... provinceDropdownFilter: "", cityDropdownFilter: "", filteredCities: [], ... setProvinceDropdownFilter: (value: string) => set({ provinceDropdownFilter: value }), setCityDropdownFilter: (value: string) => set({ cityDropdownFilter: value }), setFilteredCitiesFilter: (value: string[]) => set({ filteredCities: value }), ... })) );
问题分析
- Dropdown未使用筛选后的城市列表:你在Header中计算出了
filteredCities并存入状态,但Dropdown组件完全忽略了这个状态,始终从原始data生成所有城市选项,没有应用省份筛选逻辑。 - Dropdown选项生成逻辑缺失:当前
filteredOptions仅过滤存在对应字段的项,没有结合省份筛选条件,且代码中未明确uniqueValues的生成逻辑(即使存在,也未关联省份状态)。 - 状态同步问题:切换省份时未清空已选中的城市,可能导致选中的城市不在新的筛选列表中。
修复方案
1. 修改Dropdown组件,支持接收筛选后的选项
给Dropdown新增filteredOptions props,当为城市类型时优先使用传入的筛选结果:
export const Dropdown: React.FC<DropdownProps> = ({ data, onChange, value, filterType, filteredOptions: propFilteredOptions, // 新增props }) => { const filteredData = data.map((group) => group.equipments).flat(); // 优先使用传入的筛选选项,否则从原始数据生成 const rawOptions = propFilteredOptions ?? filteredData.map(item => { switch(filterType) { case "manufacturer": return item.manufacturer; case "state": return item.state; case "city": return item.city; default: return ""; } }).filter(Boolean); // 去重并排序 const uniqueValues = new Set(rawOptions); const sortedValues = Array.from(uniqueValues).sort(); const handleFilters = (e: React.ChangeEvent<HTMLSelectElement>) => { onChange(e); }; return ( <Select aria-label="Select" placeholder={getCustomPlaceholder(filterType) as string} value={value} onChange={handleFilters} > {sortedValues.map((val) => ( <option key={val} value={val}> {val} </option> ))} </Select> ); }; // 更新Props类型定义 interface DropdownProps { data: any; // 替换为你的实际数据类型 onChange: (e: React.ChangeEvent<HTMLSelectElement>) => void; value: string; filterType: "manufacturer" | "state" | "city"; filteredOptions?: string[]; // 新增可选props }
2. 修改Header组件,传递筛选后的城市列表给Dropdown
引入filteredCities状态,并传给城市Dropdown:
export const Header = ({ data, isLoading, error }: HeaderProps) => { // 新增filteredCities状态 const { provinceDropdownFilter, cityDropdownFilter, filteredCities, } = useFilterStore(); const filteredData = data.map((group) => group.equipments).flat(); const handleDropdownFilterProvince = ( e: React.ChangeEvent<HTMLSelectElement> ) => { const selectedProvince = e.target.value; useFilterStore.setState({ provinceDropdownFilter: selectedProvince, cityDropdownFilter: "" // 切换省份时清空城市选择 }); const filteredCitiesSet = new Set<string>( filteredData .filter((item) => item.state === selectedProvince) .map((item) => item.city) ); useFilterStore.setState({ filteredCities: Array.from(filteredCitiesSet) }); }; const handleDropdownFilterCity = ( e: React.ChangeEvent<HTMLSelectElement> ) => { useFilterStore.setState({ cityDropdownFilter: e.target.value }); }; return ( <> ... <Dropdown data={data} value={manufacturerDropdownFilter} onChange={handleDropdownFilterManufacturer} filterType="manufacturer" /> <Dropdown data={data} value={provinceDropdownFilter} onChange={handleDropdownFilterProvince} filterType="state" /> <Dropdown data={data} value={cityDropdownFilter} onChange={handleDropdownFilterCity} filterType="city" filteredOptions={filteredCities} {/* 传入筛选后的城市 */} /> ... </> ); };
3. 优化状态更新(可选)
封装Zustand的action,让状态更新逻辑更集中:
const useFilterStore = create<FilterState>( zukeeper((set) => ({ provinceDropdownFilter: "", cityDropdownFilter: "", filteredCities: [], // 封装省份更新逻辑 updateProvinceFilter: (value: string, rawData: any[]) => { const filteredData = rawData.map((group) => group.equipments).flat(); const citySet = new Set<string>( filteredData .filter(item => item.state === value) .map(item => item.city) ); set({ provinceDropdownFilter: value, cityDropdownFilter: "", filteredCities: Array.from(citySet) }); }, setCityDropdownFilter: (value: string) => set({ cityDropdownFilter: value }), })) ); // Header中调用action const handleDropdownFilterProvince = ( e: React.ChangeEvent<HTMLSelectElement> ) => { useFilterStore.getState().updateProvinceFilter(e.target.value, data); };
关键修复点总结
- 城市Dropdown必须接收并使用从省份筛选出的城市列表,而非原始数据
- 切换省份时清空城市选择,避免无效选项残留
- 确保Dropdown的选项生成逻辑包含去重和排序
内容的提问来源于stack exchange,提问作者jrad09
相关产品推荐
相关产品推荐

