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

react-select如何通过API异步数据设置defaultValue默认值

问题根因

你的判断是对的,问题出在异步加载时序上:react-select的defaultValue属性只在组件首次挂载时读取一次,后续state更新不会触发它重新赋值。
你当前代码里组件第一次渲染的时候,defaultCity是初始空对象,cities是空数组,Select初始化拿不到有效默认值;等两个异步接口返回数据、state更新完成时,Select早就挂载完了,不会再重新读defaultValue,所以哪怕你打印defaultCity值是正确的,组件也不会显示选中状态。

修复方案

两种常用写法,优先选第一种,是React生态的标准受控用法,不会踩时序坑。

方案1:改成受控组件(推荐)

把非受控的defaultValue换成受控的value属性,绑定onChange事件同步选中值,只要state更新,Select就会自动同步选中状态,完全不受异步加载顺序影响:
首先调整状态和接口逻辑:

const [request, setRequest] = useState<IRequest>();
const [cities, setCities] = useState<ICity[]>([]);
// 直接维护当前选中的城市值,不需要单独的defaultCity state
const [selectedCity, setSelectedCity] = useState<{value: string, label: string} | null>(null);

useEffect(() => {
    const initData = async () => {
        // 用Promise.all并行拉取两个接口,比分开写更快
        const [requestRes, citiesRes] = await Promise.all([
            axios.get<IRequest>(`/api/requests/${id}`),
            axios.get<ICity[]>('/api/cities')
        ])
        setRequest(requestRes.data)
        setCities(citiesRes.data)
        // 接口返回后设置默认选中值
        setSelectedCity({
            value: requestRes.data.city.code,
            label: requestRes.data.city.name
        })
    }
    initData()
}, [])

然后修改Select组件的属性:

<Select
    placeholder='City'
    value={selectedCity}
    onChange={(newVal) => setSelectedCity(newVal as {value: string, label: string})}
    options={
        cities.map(city => ({
            value: city.code,
            label: city.name
        }))
    }
/>

方案2:数据加载完成后再渲染Select

如果你想保留非受控写法,就加一层加载判断,等城市列表、默认城市值都拉取完成后再渲染Select组件,保证组件首次挂载时就能拿到完整的defaultValue和匹配的options:

const [request, setRequest] = useState<IRequest>();
const [cities, setCities] = useState<ICity[]>([]);
const [defaultCity, setDefaultCity] = useState<{value: string, label: string}>({} as any);
// 新增加载状态
const [pageLoading, setPageLoading] = useState(true);

useEffect(() => {
    const initData = async () => {
        setPageLoading(true)
        const requestRes = await axios.get<IRequest>(`/api/requests/${id}`)
        const citiesRes = await axios.get<ICity[]>('/api/cities')
        setRequest(requestRes.data)
        setCities(citiesRes.data)
        setDefaultCity({
            value: requestRes.data.city.code,
            label: requestRes.data.city.name
        })
        setPageLoading(false)
    }
    initData()
}, [])

// 加载过程中显示占位,加载完成再渲染Select
{pageLoading ? (
    <div>加载中...</div>
) : (
    <Select
        placeholder='City'
        defaultValue={defaultCity}
        options={
            cities.map(city => ({
                value: city.code,
                label: city.name
            }))
        }
    />
)}

注意:用这个方案要保证defaultCity的value和options列表里某一项的value完全相等(类型也要一致,比如都是字符串,不要出现一个是数字1一个是字符串"1"的情况),否则react-select匹配不到对应选项,也不会显示选中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 03:51:25