You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Hooks中HTML Select城市选项默认选中失效的问题

解决React Hooks中城市选择框默认选中不生效的问题

你的问题出在React状态更新的异步性上:调用regionChanged时,setCities是异步操作,不会立即更新DOM中的城市选项列表。当你执行cityRef.current.value = user.city时,对应的<option>还没渲染出来,所以无法触发选中状态。

下面是两种可行的解决方法:

方法一:使用受控组件(推荐,符合React数据流)

放弃直接操作DOM,用状态来控制选择框的选中值,这是React的标准做法:

const [regions, setRegions] = useState([]);
const [cities, setCities] = useState([]);
// 新增状态控制选中值
const [selectedRegion, setSelectedRegion] = useState('');
const [selectedCity, setSelectedCity] = useState('');

const citiesAndRegions = [
    {
        _id: 123, name: 'California', cities: [{id: 'abc', name: 'LA'},{id: 'efg', name: 'Hollywood'}]
    },
    {
        _id: 456, name: 'Florida', cities: [{id: 'hji', name: 'Miami'}]
    }
];

const regionChanged = (id) => {
    const found = citiesAndRegions.find(el => el._id === Number(id));
    setCities(found.cities);
}

useEffect(() => {
    const fetchRegions = () => {
        const region_result = [{_id: 123, name: 'California'},{_id: 456, name: 'Florida'}];
        region_result.forEach(el => {
            el.value = el._id;
            el.label = el.name;
        });
        setRegions(region_result);
    }
    const setDefaultValues = () => {
        const user = {name: 'Jack', region: 123, city: 'abc'};
        fetchRegions();
        // 设置默认选中的地区和城市
        setSelectedRegion(user.region);
        const foundRegion = citiesAndRegions.find(el => el._id === user.region);
        setCities(foundRegion.cities);
        setSelectedCity(user.city);
    }
    setDefaultValues();
}, []);

// 监听选中地区变化,同步更新城市列表
useEffect(() => {
    if (selectedRegion) {
        const foundRegion = citiesAndRegions.find(el => el._id === Number(selectedRegion));
        setCities(foundRegion.cities);
    }
}, [selectedRegion]);

return(
    <>
        <select 
            value={selectedRegion} 
            onChange={e => setSelectedRegion(e.target.value)}
        >
            {
                regions.map((opt) =>
                    <option key={opt._id} value={opt.value}>{opt.label}</option>
                )
            }
        </select>
        <select 
            value={selectedCity}
            onChange={e => setSelectedCity(e.target.value)}
        >
            {
                cities.map((opt) =>
                    <option key={opt.id} value={opt.id}>{opt.name}</option>
                )
            }
        </select>
    </>
);

方法二:使用ref配合useEffect监听cities变化

如果坚持要用ref操作DOM,需要等cities状态更新、DOM渲染完成后再设置ref的值:

const [regions, setRegions] = useState([]);
const [cities, setCities] = useState([]);
const regionRef = useRef(null);
const cityRef = useRef(null);
// 存储默认城市ID,等待城市列表渲染后再设置
const [defaultCityId, setDefaultCityId] = useState('');

const citiesAndRegions = [
    {
        _id: 123, name: 'California', cities: [{id: 'abc', name: 'LA'},{id: 'efg', name: 'Hollywood'}]
    },
    {
        _id: 456, name: 'Florida', cities: [{id: 'hji', name: 'Miami'}]
    }
];

const regionChanged = (id) => {
    const found = citiesAndRegions.find(el => el._id === Number(id));
    setCities(found.cities);
}

useEffect(() => {
    const fetchRegions = () => {
        const region_result = [{_id: 123, name: 'California'},{_id: 456, name: 'Florida'}];
        region_result.forEach(el => {
            el.value = el._id;
            el.label = el.name;
        });
        setRegions(region_result);
    }
    const setDefaultValues = () => {
        const user = {name: 'Jack', region: 123, city: 'abc'};
        fetchRegions();
        regionRef.current.value = user.region;
        regionChanged(user.region);
        // 先缓存默认城市ID
        setDefaultCityId(user.city);
    }
    setDefaultValues();
}, []);

// 监听城市列表变化,渲染完成后设置选中值
useEffect(() => {
    if (cities.length > 0 && defaultCityId && cityRef.current) {
        cityRef.current.value = defaultCityId;
    }
}, [cities, defaultCityId]);

return(
    <>
        <select ref={regionRef} onChange={e => regionChanged(e.target.value)}>
            {
                regions.map((opt) =>
                    <option key={opt._id} value={opt.value}>{opt.label}</option>
                )
            }
        </select>
        <select ref={cityRef}>
            {
                cities.map((opt) =>
                    <option key={opt.id} value={opt.id}>{opt.name}</option>
                )
            }
        </select>
    </>
);

额外注意点

  • regionChanged中e.target.value是字符串类型,而el._id是数字,需要用Number(id)转换后再匹配,避免查找失败。
  • 优先使用受控组件方案,更符合React单向数据流理念,代码维护性更强。

内容的提问来源于stack exchange,提问作者oderfla

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 12:30:42