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

如何对比两个API返回的ID数组,过滤重复ID并更新options状态?

问题:过滤API返回的重复ID并生成指定格式的选项数组

我通过两次不同的API调用得到两个ID数组,想要过滤掉已存在于第一个数组(prevAdmins)中的ID,把剩余ID以{value: ID, label: 名称}的格式存入options状态,但现有代码没实现这个需求,求帮忙。

现有代码

const [prevAdmins, setPrevAdmins] = useState<any>([]);
const [options, setOptions] = useState([{value: "", label: ""}]);

// API 1 CALL 
get_user_groups({bot_id: params.botid, group_id: params.userid}).then((res) => {
  setDetails(res?.data?.data[0]);
  setGroupName(res?.data?.data[0].name)
  let prevAdmins: any = [];
  res?.data?.data[0]?.join_details.map((prevJoinee, idx) => {
    prevAdmins.push(prevJoinee.user_id)
    setPrevAdmins(prevAdmins)
  })
});

// API 1 返回结果:prevAdmins = ['61dfcfb71f492f4f4f589e93', '61dedd23bd15322626dd7539']

// 2nd API CALL : 
get_followers({bot_id: params.botid}).then((res) => {
  if(res.data.data){
    let option: any = [];
    let allAdmins: any = [];
    res.data.data.map((admin, index) => {
      allAdmins.push(admin._id);
      if(!prevAdmins.includes(allAdmins)){
        option.push({value: admin._id, label: admin.displayName})
      }
    })
    setOptions(option);
  }
})

// API 2 返回结果:['61dfd02a1f492f4f4f589f00', '61dfcfb71f492f4f4f589e93', '61dedd23bd15322626dd7539']

问题分析

现有代码存在几个关键问题:

  • API异步顺序问题:两个API并行调用,可能第二个API先返回,此时prevAdmins还是初始空数组,过滤逻辑完全失效。
  • 状态更新错误:第一个API在map循环中多次调用setPrevAdmins,应该在循环结束后一次性更新状态;且内部变量prevAdmins和状态变量重名,易造成混淆。
  • 过滤逻辑错误:第二个API中用!prevAdmins.includes(allAdmins),但allAdmins是数组,而prevAdmins存储的是单个ID值,应该判断当前admin._id是否不在prevAdmins数组中。

修正后的代码方案

方案1:确保API调用顺序(先执行第一个API,再调用第二个)

const [prevAdmins, setPrevAdmins] = useState<any>([]);
const [options, setOptions] = useState([{value: "", label: ""}]);

// 合并API调用,保证顺序
const fetchData = async () => {
  // 先调用第一个API获取prevAdmins
  const groupRes = await get_user_groups({bot_id: params.botid, group_id: params.userid});
  if (groupRes?.data?.data[0]) {
    setDetails(groupRes.data.data[0]);
    setGroupName(groupRes.data.data[0].name);
    // 提取所有需要排除的ID
    const adminIds = groupRes.data.data[0].join_details.map(item => item.user_id);
    setPrevAdmins(adminIds);
    
    // 调用第二个API并过滤
    const followerRes = await get_followers({bot_id: params.botid});
    if (followerRes.data.data) {
      // 转成Set提升查找效率
      const excludeIds = new Set(adminIds);
      const filteredOptions = followerRes.data.data
        .filter(admin => !excludeIds.has(admin._id))
        .map(admin => ({value: admin._id, label: admin.displayName}));
      setOptions(filteredOptions);
    }
  }
};

// 组件挂载时执行
useEffect(() => {
  fetchData();
}, [params.botid, params.userid]);

方案2:用useEffect监听prevAdmins变化,触发第二个API

如果两个API不需要严格顺序,或者第一个API可能多次更新,可使用这种方式:

const [prevAdmins, setPrevAdmins] = useState<any>([]);
const [options, setOptions] = useState([{value: "", label: ""}]);

// 第一个API调用
useEffect(() => {
  get_user_groups({bot_id: params.botid, group_id: params.userid}).then((res) => {
    if (res?.data?.data[0]) {
      setDetails(res.data.data[0]);
      setGroupName(res.data.data[0].name);
      const adminIds = res.data.data[0].join_details.map(item => item.user_id);
      setPrevAdmins(adminIds);
    }
  });
}, [params.botid, params.userid]);

// 监听prevAdmins变化,调用第二个API并过滤
useEffect(() => {
  // 只有当prevAdmins有值时才调用第二个API
  if (prevAdmins.length === 0) return;
  
  get_followers({bot_id: params.botid}).then((res) => {
    if (res.data.data) {
      const excludeIds = new Set(prevAdmins);
      const filteredOptions = res.data.data
        .filter(admin => !excludeIds.has(admin._id))
        .map(admin => ({value: admin._id, label: admin.displayName}));
      setOptions(filteredOptions);
    }
  });
}, [prevAdmins, params.botid]);

说明

  • 用Set存储需要排除的ID,has方法的查找效率比数组includes更高,数据量大时优势明显。
  • 统一处理API异步逻辑,避免因顺序问题导致的过滤失效。
  • 去掉循环中多次更新状态的错误写法,改为一次性更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 20:43:52