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

React如何等待axios数据请求完成后再渲染select下拉选项

问题根源

你的下拉框为空核心是异步逻辑时序错误,叠加几个代码bug:

  • 两个axios.get是异步非阻塞操作,发起请求后代码会立刻往下执行,此时接口还没返回,data1和data2还是初始的空数组,自然处理不出任何选项。
  • React的状态更新是异步批处理的,就算接口返回调用了setData1/setData2,在同一个useEffect的同步执行上下文里也拿不到更新后的状态值。
  • 代码存在语法错误:两个axios.get的第二个配置参数没写闭合就直接接了.then,运行时会直接抛错。
  • 处理选项的逻辑有问题:在data1.map循环里反复调用setOptions,每次调用都会覆盖之前的选项值,最终只会保留最后一次循环的结果;而且最后传给setOptions的是过滤后的原始数组y,不是你已经格式化成{value, label}结构的z数组,渲染时自然读不到label字段。
正确实现方案

不要等两个状态更新后再处理选项,直接用async/await配合Promise.all等两个接口都返回后,当场处理完数据再一次性设置选项,同时加加载态避免空框体验问题。

修正后的完整逻辑代码:

const [data1, setData1] = useState([]);
const [data2, setData2] = useState([]);
const [options, setOptions] = useState([]);
const [loading, setLoading] = useState(true);

useEffect(() => {
  // useEffect回调不能直接加async,需要在内部定义异步函数
  const loadData = async () => {
    try {
      setLoading(true);
      // 并行发起两个请求,等全部返回后再往下走,比串行请求速度快
      const [res1, res2] = await Promise.all([
        axios.get('第一个接口的url'),
        axios.get('第二个接口的url')
      ]);

      // 直接从接口响应取数据,不用等状态更新
      const list1 = res1.status === 200 ? res1.data : [];
      const list2 = res2.status === 200 ? res2.data : [];

      // 如果其他逻辑需要用到原始数据,再存到状态里
      setData1(list1);
      setData2(list2);

      // 一次性处理完所有选项
      const finalOptions = [];
      list1.forEach(info1 => {
        const matchedUsers = list2.filter(info2 => info1.id === info2.id);
        matchedUsers.forEach(user => {
          finalOptions.push({
            // value建议用唯一基本类型值,不要传整个对象,方便后续取值对比
            value: user.id,
            label: user.username
          })
        })
      })

      setOptions(finalOptions);
    } catch (err) {
      console.error('数据加载失败', err);
      // 这里可以加自己的错误提示逻辑
    } finally {
      setLoading(false);
    }
  }

  loadData();
}, []);

渲染部分调整,增加加载态:

<select value={selectedOption} onChange={handleChange} className='w-40' disabled={loading}>
  {loading ? (
    <option value="">加载中...</option>
  ) : (
    options.map(option => (
      <option key={option.value} value={option.value}>
        {option.label}
      </option>
    ))
  )}
</select>
关键说明
  • 不要给useEffect的入参回调直接加async,async函数会返回Promise,而useEffect要求回调要么返回空,要么返回组件卸载时的清理函数,直接加async会导致React无法正确执行清理逻辑。
  • 接口数据拿到后可以直接处理,不需要先存到state再从state里读出来处理,能减少一次不必要的重渲染,也能避开闭包拿不到最新状态的问题。
  • 渲染列表项时记得给<option>加唯一的key属性,避免React渲染告警和更新异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 21:15:43