Если я правильно понял, ваше состояние должно иметь:
products
массив - содержащий ваши продукты. brands
массив - содержащий ваших производителей.
Если это правильно, то я вижу пару проблем с вашим кодом:
- You ' слишком сложные методы массива, приводящие к желаемому поведению.
- Теперь реальная проблема заключается в том, что при первом фильтровании вы теряете доступ ко всем продуктам, и, следовательно, вам необходимо повторно выбирать их каждый фильтр клик.
Получив это, вот ваш обновленный код:
import React, {useEffect} from 'react'
import Loader from './../Loader/Loader'
import ProductItem from './ProductItem'
function Catalog() {
const [products, setProducts] = React.useState([])
const [brands, setBrands] = React.useState([])
const [brand, setBrand] = React.useState('')
useEffect(() => {
const proxyUrl = 'https://cors-anywhere.herokuapp.com/'
const url = 'https://avtodoka-msk.ru/aimylogic-mission.json'
fetch(proxyUrl + URL)
.then(response => response.json())
.then(products => {
if (brands.length <= 0)
setBrandsFromProducs(products)
const filteredProducts = products.filter(product => !brand || product.brend.includes(brand))
setProducts(filteredProducts)
})
}, [brand])
function setBrandsFromProducs(products) {
const brands = products.reduce(
(acc, product) => ([...acc, ...product.brend])
, [])
setBrands([...new Set(brands)])
}
function toggleBrand(e) {
const selectedBrand = e.target.value
setBrand(selectedBrand)
}
}
Ключевые аспекты:
product.brend
- это массив , Чтобы извлечь все бренды из этого JSON, вам нужно сгладить массив массивов, поэтому вы уменьшаете его до плоского массива - следовательно, используется .reduce()
. Это нужно делать только в том случае, если массив brands
пуст. Однако, если вас не беспокоит производительность, вы можете удалить оператор if
, чтобы всегда сбрасывать массив brands
. - Ваше событие выбирает марку, оно не должно содержать никаких других побочных эффектов. (фильтрация товаров). Те должны жить в надлежащем объеме ->
useEffect
. Чтобы вызвать это событие, вам необходимо «прослушать» изменения в фильтре brand
, поэтому его необходимо указать как зависимость useEffect
. - В вашем
filter
отсутствует return false
вне оператора if
. Однако это можно упростить, поскольку .include () возвращает логическое значение и не изменяет исходный массив. Фильтр, который я создал, сначала проверит, есть ли у вас активный фильтр, и фильтрует его только в том случае, если он у вас есть. - Необходимо убедиться, что
e.target.value
- это точная строка из массива product.brend
.
Небольшие предложения:
- Если вы управляете API, ваши фильтры всегда должны быть на стороне сервера, чтобы избежать больших полезных нагрузок, чем вам нужно.
- Если вы не используете состояние
brand
, вы можете безопасно удалить его. Без вашего JSX я не могу быть уверен.