如何对请求数据做唯一性过滤?附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
相关产品推荐
相关产品推荐

