У меня есть API, который возвращает 5000 изображений. Я хочу получить первое изображение из каждого альбома с четным идентификатором в React с помощью Fetch.
Проблема в том, что не могу понять, как фильтровать данные, чтобы получить те, у которых есть четные идентификаторы и первое изображение альбомов с четными идентификаторами.
import React, {useState, useEffect} from 'react';
// Import Materials from Material-ui
import {Grid} from '@material-ui/core';
const Album = () => {
const [images, setImages] = useState([]);
const [imagesCount, setImagesCount] = useState(10);
const api = 'https://jsonplaceholder.typicode.com/photos';
useEffect(() => {
fetch(api)
.then(res => res.json())
.then(data => {
const filterData = data.filter(x => x.albumId % 2 === 0);
for(const url of filterData) {
if (url.albumId % 2 === 0) {
// How to get only the first even ablumID url of each even albumID?
}
}
setImages(filterData);
console.info(filterData);
})
.catch(err => console.info(err))
}, []);
return (
<div>
<Grid container spacing = {3} alignItems = "center">
{images.map((album) => (
<Grid item key = {album.id} xs = {12} sm = {6} md = {4}>
<img className = "albumImg" src = {album.url} alt = {album.title} />
</Grid>
))}
</Grid>
</div>
)
}
export default Album;
data.filter(x => x.albumId % 2 === 0) на самом деле ничего не фильтрует.
Смотрите мой обновленный комментарий.
data.filter(x => x.albumId% 2 === 0); вы пытаетесь отфильтровать идентификаторы, которые являются четными числами, или вы пытаетесь получить идентификатор === 0?
Я пытаюсь отфильтровать идентификаторы с четными числами.
Вы пробовали то, что я предложил?
Как сказал @goto1, вам нужно назначить результат этого фильтра. data = data.filter(x => x.albumId % 2 === 0);
developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
@goto1 goto1 Я сделал то, что вы предложили, добавив к константе - const filterData = data.filter(x => x.albumId % 2 === 0);
и добавил в setImages, ничего не изменилось. Я все еще получаю 5000 альбомов без фильтрации.
Я обновил свой код в своем вопросе
Это определенно должно помочь - это работает на моем конце. Что вы получаете, когда вы console.info(data.length)
против console.info(filteredData.length)
?
@ goto1, это определенно помогло! Я смотрел журнал из данных, а не из filterData, oppps, спасибо. Теперь, как я могу получить только первое изображение из каждого четного альбома?
Не уверен, что вы имеете в виду, вы говорите массив url
s? Это то, что вы хотите для массива images
?
Да, я хочу получить первый URL-адрес каждого первого четного массива. Таким образом, URL-адрес первого изображения из альбомного идентификатора 2, 4 и 6 и т. д., но только первое изображение из каждого четного альбомного идентификатора.
Смотрите мой ответ ниже.
Что касается первой проблемы, Array.prototype.filter
не изменяет существующий массив, а вместо этого возвращает новый массив с элементами, которые проходят тест, поэтому вам нужно сохранить этот новый массив в переменной и использовать ее для обновления вашего состояния,
const api = "https://jsonplaceholder.typicode.com/photos";
fetch(api)
.then((res) => res.json())
.then((data) => {
const filterData = data.filter((x) => x.albumId % 2 === 0);
console.info("original", data.length);
console.info("filtered", filterData.length);
})
.catch((err) => console.info(err));
Что касается вашей второй проблемы, если вы хотите создать новый массив с элементами, которые имеют уникальные albumId
s, вы можете использовать Array.prototype.reduce
для перебора всех элементов и добавления только тех, которых еще нет в accumulator
,
const api = "https://jsonplaceholder.typicode.com/photos";
fetch(api)
.then((res) => res.json())
.then((data) => {
const filterData = data.filter((x) => x.albumId % 2 === 0);
const uniqueItems = filterData.reduce((accumulator, item) => {
const isDuplicateItem = accumulator.find(
(i) => i.albumId === item.albumId
);
// append the item if there's no existing
// item in the array with the same `albumId`
if (!isDuplicateItem) {
return [...accumulator, item];
}
return accumulator;
}, []);
console.info("uniqueItems", uniqueItems.length);
console.info(uniqueItems[0]);
console.info(uniqueItems[1]);
})
.catch((err) => console.info(err));
Смотрите больше, если нужно:
Но как я могу получить только первый массив каждого четного массива?
@Rastezzy, можете ли вы уточнить, что вы подразумеваете под «первым массивом каждого четного массива»? Вы перебираете массив объектов со следующими свойствами: {albumId: number, id: number, title: string, url: string, thumbnailUrl: string}
. О каком array
ты говоришь?
Извините за плохое использование терминов, я имел в виду объекты. Теперь, поскольку у нас есть несколько объектов с похожими альбомными идентификаторами, мне просто нужен URL-адрес из первого альбомного идентификатора только первого четного числа. Таким образом, первый URL-адрес первого объекта только с альбомным идентификатором 2, а не остальные с альбомным идентификатором 2 и т. д. Имеет ли это смысл?
Я обновил свой код, это самый близкий к ответу ответ.
@Rastezzy, посмотри мое редактирование - я думаю, это то, что ты ищешь.
@Rastezzy Я только что понял, что это должно быть filterData.reduce
, а не data.reduce
- вам нужен уникальный albumIds
только для тех, у кого четные числа, поэтому я внес изменения, но вы поняли идею.
Я уже сделал это в своем коде, да, я понял.
Я этого не делал, не знаю почему, но отмечу заново.
Так в чем проблема, с которой вы столкнулись? Кстати,
Array.prototype.filter
возвращает новый массив и не изменяет старый массив, поэтому, если вы хотите вызватьsetImages
для отфильтрованного массива, вам следует сохранить этот новый массив в переменной и использовать ее для установки вашегоstate
.