如何在React.js单个组件中多次实现基于选中国家的州/省下拉框数据填充
解决React多组国家-州下拉框联动互相干扰的问题
这个问题的核心原因很清晰:你现在把所有下拉框的选中状态和州列表数据都存在了父组件的全局状态里(selectedCountry和state),所以不管修改哪一组的国家选择,都会更新这个全局状态,导致所有州下拉框同步变化。
解决办法就是把单组的国家-州联动逻辑封装成独立的子组件,让每组下拉框拥有自己独立的状态,互不影响。下面是具体的实现方案:
步骤1:封装独立的联动子组件
创建一个CountryStateSelector组件,把单组的状态管理、数据过滤逻辑都放在这个组件内部:
import React, { useState, useEffect } from "react"; import { TextField, MenuItem } from "@mui/material"; // 可以把数据源放在这里,或者作为props传入(如果需要复用不同数据源的话) const stateCountryData = [ { state_ID: 1, state: "Delhi", country_ID: 1, country_name: "India" }, { state_ID: 2, state: "Mumbai", country_ID: 1, country_name: "India" }, { state_ID: 3, state: "Calgary", country_ID: 2, country_name: "Canada" }, { state_ID: 4, state: "Toronto", country_ID: 2, country_name: "Canada" } ]; export default function CountryStateSelector() { const [countries, setCountries] = useState([]); const [states, setStates] = useState([]); const [selectedCountry, setSelectedCountry] = useState(""); // 初始化获取去重后的国家列表 useEffect(() => { const uniqueCountries = [ ...new Map(stateCountryData.map(item => [item.country_name, item])).values() ]; setCountries(uniqueCountries); // 初始默认显示所有州 setStates(stateCountryData); // 如果需要默认选中第一个国家,可以取消下面注释: // setSelectedCountry(uniqueCountries[0]?.country_name || ""); }, []); // 根据选中的国家过滤州列表 useEffect(() => { if (!selectedCountry) { setStates(stateCountryData); return; } const filteredStates = stateCountryData.filter( item => item.country_name === selectedCountry ); setStates(filteredStates); }, [selectedCountry]); return ( <div style={{ display: "flex", gap: "1rem", marginBottom: "1rem" }}> <TextField select name="Country" label="Country" variant="outlined" size="small" value={selectedCountry} onChange={(event) => setSelectedCountry(event.target.value)} > {countries.map(opt => ( <MenuItem key={opt.country_name} value={opt.country_name}> {opt.country_name} </MenuItem> ))} </TextField> <TextField select name="state" label="State" variant="outlined" size="small" value="" > {states.map(opt => ( <MenuItem key={opt.state_ID} value={opt.state}> {opt.state} </MenuItem> ))} </TextField> </div> ); }
步骤2:在父组件中复用子组件
现在你只需要在父组件里多次渲染这个子组件就行,每组都会有自己独立的状态:
import React from "react"; import "./styles.css"; import CountryStateSelector from "./CountryStateSelector"; export default function App() { return ( <div className="App"> <CountryStateSelector /> <hr /> <CountryStateSelector /> <hr /> {/* 还可以继续添加更多组 */} <CountryStateSelector /> </div> ); }
关键优化点说明
- 状态隔离:每个
CountryStateSelector实例都有自己的selectedCountry和states状态,修改其中一组不会影响其他组 - 代码复用:把重复的逻辑抽成子组件,父组件代码变得简洁,后续添加更多组只需要多写一行组件调用
- 细节优化:移除了MenuItem上多余的
onChange(TextField的onChange已经能处理选中逻辑),用state_ID作为州选项的key(比state名称更稳定)
这样修改后,每组下拉框的联动逻辑就完全独立了,再也不会出现互相影响的问题啦!
内容的提问来源于stack exchange,提问作者Rohit Verma
相关产品推荐
相关产品推荐

