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

如何对请求数据做唯一性过滤?附React代码咨询

问题:React中实现猫咪数据唯一性过滤,用Filter思路是否正确?

需求:对请求获取的数据进行唯一性过滤,仅汇总唯一数据。
场景说明:选择数字4时总数变为4;选择数字5时,总数本该增加5,但实际仅需增加1,因仅加载了一张唯一图片。尝试通过filter实现该逻辑但未成功,请问思路是否正确?

原代码

import { useEffect, useState } from "react";
import { Cat, fetchCats } from "../api/services/CatsService";
import { DropdownMenu, MenuItem } from "./Dropdown/Dropdown";
import { Header } from "./Header/Header";
import { Select } from "./Select/Select";

export function MainPage() {
  const [cats, setCats] = useState<Cat[]>([]);
  const [numberInSelect, setOption] = useState<number>(
    Number(localStorage.getItem("numberInSelect") || 3)
  );

  useEffect(() => {
    localStorage.setItem("numberInSelect", JSON.stringify(numberInSelect));
    const cachedData = localStorage.getItem("someData");

    const parse = JSON.parse(cachedData);
    if (cachedData) {
      if (parse.length < numberInSelect) {
        fetchCats(numberInSelect - parse.length).then((data) => {
          const array = [];
          array.push(...data);
          array.push(...parse);
          localStorage.setItem("someData", JSON.stringify(array));
          setCats(array);
        });
      }

      const rew = parse.slice(0, numberInSelect);
      setCats(rew);
    } else {
      fetchCats(numberInSelect).then((data) => {
        localStorage.setItem("someData", JSON.stringify(data));
        setCats(data);
      });
    }
  }, [numberInSelect]);

  return (
    <>
      <div>
        <Header title={"Всего котов загружено:"} option={numberInSelect} />

        <Select
          label={"Pick a number"}
          options={[3, 4, 5]}
          title={"Cats"}
          setCats={setCats}
          setOption={setOption}
          option={numberInSelect}
        />
      </div>
      <div className="title-list-info">
        {" "}
        <CatList title={"Cats list: "} cats={cats} />
      </div>
    </>
  );
}

思路正确性分析

用filter实现去重的思路是完全正确的,但你当前的代码根本没做去重逻辑——只是把新请求的数据和缓存数据直接拼接,自然会出现重复内容。核心问题是你需要基于猫咪数据的唯一标识(比如id,假设Cat类型包含该字段)判断重复,再用filter结合唯一性校验完成过滤。

具体修改方案

1. 核心修改:添加去重逻辑

假设Cat接口包含唯一id字段,在合并新数据和缓存数据时,先过滤重复项再更新状态和本地存储:

useEffect(() => {
  localStorage.setItem("numberInSelect", JSON.stringify(numberInSelect));
  const cachedData = localStorage.getItem("someData");

  if (cachedData) {
    const parse = JSON.parse(cachedData) as Cat[];
    if (parse.length < numberInSelect) {
      fetchCats(numberInSelect - parse.length).then((newCats) => {
        // 合并新数据与缓存数据
        const combined = [...newCats, ...parse];
        // 用filter结合findIndex实现去重(基于id)
        const uniqueCats = combined.filter((cat, index, self) => 
          index === self.findIndex(c => c.id === cat.id)
        );
        // 也可以用更高效的Set方式:
        // const idSet = new Set();
        // const uniqueCats = combined.filter(cat => {
        //   if (idSet.has(cat.id)) return false;
        //   idSet.add(cat.id);
        //   return true;
        // });
        
        localStorage.setItem("someData", JSON.stringify(uniqueCats));
        // 取前numberInSelect个唯一数据更新状态
        setCats(uniqueCats.slice(0, numberInSelect));
      });
    } else {
      // 缓存数据足够时,直接取前numberInSelect个
      setCats(parse.slice(0, numberInSelect));
    }
  } else {
    fetchCats(numberInSelect).then((data) => {
      localStorage.setItem("someData", JSON.stringify(data));
      setCats(data);
    });
  }
}, [numberInSelect]);

2. 修复异步状态覆盖问题

原代码中,异步请求的setCats(array)会被后面同步执行的setCats(rew)覆盖,因为异步请求是延迟完成的,必须把setCats(rew)放到else分支中,避免状态被意外覆盖。

3. 无id字段的替代方案

如果Cat类型没有id,可以用图片的url作为唯一标识(假设每张图片的url唯一),只需把去重逻辑中的c.id === cat.id替换为c.url === cat.url即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 04:05:43