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

React调用Spotify API返回专辑对象数组的去重实现方案

React调用Spotify API获取专辑列表的对象数组去重方案

问题场景

在React项目中调用Spotify API拉取艺人专辑JSON数据时,返回结果存在大量同名重复专辑,需要对存入useState对象数组状态的专辑数据做去重处理。
原实现逻辑为:请求接口后循环遍历返回条目,逐条调用setAlbums()追加到状态中,原代码如下:

const artistInfoHandler = (id) => {
    setLoading(true);
    setAlbums([]);
    fetch(`https://api.spotify.com/v1/artists/${id}/albums`, {
      headers: {
        Accept: "application/json",
        Authorization: `Bearer ${data.access_token}`,
        "Content-Type": "application/json",
      },
    })
      .then((response) => response.json())
      .then((response) => {
        console.log(response);
        for (let i = 0; i < response.items.length; i++) {
          setAlbums((old) => [
            ...old,
            {
              albumTitle: response.items[i].name,
              albumImage: response.items[i].images[0].url,
            },
          ]);
        }
      })
      .catch((error) => console.log(error));

    setLoading(false);
  };

代码运行后得到的专辑列表存在大量重复,示例数据如下:

0: {albumTitle: 'Certified Lover Boy', albumImage: 'xxxxxxxxxxxx'}
1: {albumTitle: 'Certified Lover Boy', albumImage: 'xxxxxxxxxxxxxxxxxx'}
2: {albumTitle: 'Dark Lane Demo Tapes', albumImage: 'xxxxxxxxxxxxxxxxxx'}
3: {albumTitle: 'Dark Lane Demo Tapes', albumImage: 'xxxxxxxxxxxx'}
// ...省略更多重复条目
19: {albumTitle: 'Nothing Was The Same', albumImage: 'xxxxxxxxxxxxxxxxxx'}

原始值类型数组使用的[...new Set(albums)]去重方案对对象数组无效。

问题原因

  • Set结构的去重逻辑基于SameValueZero相等判定,对于引用类型的对象,仅当两个对象引用地址完全一致时才会判定为相等。哪怕两个对象的属性、属性值完全相同,只要是不同的对象实例,Set也会判定为两个不同元素,因此无法直接用于对象数组去重。
  • 原代码存在两处逻辑缺陷:一是循环逐条调用setAlbums会触发多次不必要的组件重渲染;二是setLoading(false)写在fetch请求外层,会在接口还未返回结果时就提前关闭加载状态,不符合交互逻辑。
  • Spotify接口返回重复专辑的本质是同一张专辑会返回不同发行地区、不同版本的条目,需要业务侧自行根据唯一标识过滤。

实现方案

使用Map结构做去重缓存,选定专辑的唯一标识作为key判定重复,数据处理完成后一次性更新状态,同时修复原代码的加载态逻辑问题:

  • 优先选择Spotify返回的专辑id作为去重key(全局唯一,精准度最高),如果业务上需要按专辑名合并不同版本条目,也可以使用albumTitle作为去重key。
  • 遍历接口返回的专辑条目,已存在于Map中的条目直接跳过,不存在则存入Map,最终将Map的value转为数组即为去重后的列表。
  • 将loading状态的关闭逻辑放到finally回调中,确保请求无论成功失败都能正确重置加载态。

修正后的完整代码如下:

const artistInfoHandler = (id) => {
  setLoading(true);
  setAlbums([]);
  fetch(`https://api.spotify.com/v1/artists/${id}/albums`, {
    headers: {
      Accept: "application/json",
      Authorization: `Bearer ${data.access_token}`,
      "Content-Type": "application/json",
    },
  })
    .then((response) => response.json())
    .then((response) => {
      const albumMap = new Map();
      response.items.forEach(item => {
        // 用专辑id做去重key精准度更高,换成item.name即可按专辑名去重
        const uniqueKey = item.id;
        if (!albumMap.has(uniqueKey)) {
          albumMap.set(uniqueKey, {
            albumTitle: item.name,
            // 增加可选链兼容无封面的专辑数据,避免脚本报错
            albumImage: item.images[0]?.url || ''
          })
        }
      })
      // 一次性更新去重后的列表,避免多次重渲染
      setAlbums(Array.from(albumMap.values()))
    })
    .catch((error) => console.log(error))
    .finally(() => {
      setLoading(false);
    });
};

补充:如果不想保留第一条出现的专辑、需要自定义保留规则(比如优先保留高清封面的版本),可以在遍历到重复key时对比两个条目的属性,替换为符合要求的条目即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 04:06:51