Как отрендерить отфильтрованные элементы вместо отрендеренного стейта?
Есть у меня вот такой вот компонент, который должен фильтровать айтемы по категориям при нажатии на соответствующий фильтр. Сделано все, кроме, собственно, рендера. У меня есть объект, который нужно отрендерить, но я не знаю как. Вернее не знаю как его отрендерить вместо уже зарендеренных айтемов со стейта
import React, { Component } from 'react'
import Items from '../items'
import Filters from '../filters'
import Service from '../../services'
export default class Shop extends Component {
KubicService = new Service()
state = {
items: {},
filters: {}
}
componentDidMount() {
this.KubicService.getCategories()
.then((result) => {
this.setState({
filters: result.data
})
})
this.KubicService.postCatalog()
.then((result) => {
this.setState({
items: result.data
})
})
}
render(){
let filterItems = {}
const onFilterClick = (e) => {
const cats = {...this.state.filters}
const itemId = e.target.id
if(itemId === 'all') {
console.log(cats)
} else if(itemId !== 'all') {
console.log(cats[itemId].name, cats[itemId].id)
const items = this.state.items
for(let key in items) {
if(items[key].category.id == cats[itemId].id) {
console.log('false')
filterItems[key] = items[key]
console.log(filterItems)
} else {
console.log('true')
}
}
}
}
return(
<div>
<Filters onFilterClick = { onFilterClick }/>
<Items items = {this.state.items} />
</div>
)
}
}
Вот код "Items"
import React from 'react'
const Items = (props) => {
const arr = Array.from(props.items)
const elements = arr.map((item, index) => {
let url = ''
if(item && item.preview_image) {
url = 'http://*********'
url = url + item.preview_image
}
return (
<div key={index} className='store-item'>
<img className='store-item__img' src={url} alt='item img'></img>
<h3 className='store-item__title'>{item.name}</h3>
<h3 className='store-item_price'>${item.price}</h3>
</div>
)
})
return (
<div className='store-items'>
{ elements }
</div>
)
}
export default Items
А вот код "Filters"
import React from 'react'
const Filters = (props) => {
return(
<div className='store-filters'>
<div className='filter-category'>
<div className='categories'>
<button className='category-all is-active btn' id='all' onClick={ props.onFilterClick }>all</button>
<button className='category-mac btn' id='0' onClick={ props.onFilterClick }>mac</button>
<button className='category-macbook btn' id='1' onClick={ props.onFilterClick }>macbook</button>
<button className='category-iphone btn' id='2' onClick={ props.onFilterClick }>iphone</button>
<button className='category-ipad btn' id='3' onClick={ props.onFilterClick }>ipad</button>
<button className='category-watch btn' id='4' onClick={ props.onFilterClick }>watch</button>
<button className='category-airpods btn' id='5' onClick={ props.onFilterClick }>airpods</button>
</div>
<select className="filter">
<option className='filter-variable'>Price: high to low</option>
<option className='filter-variable'>Price: low to high</option>
</select>
</div>
</div>
)
}
export default Filters
Прошу помочь, ибо не знаю как такое даже загуглить
Ответы (1 шт):
В чем проблема в Items передавать не весь массив элементов, а уже отфильтрованный, в соответствии с активным фильтром? (см. пример и комменты ниже)
export default class Shop extends Component {
//ваш код
render(){
//фильтруем
const filteredItems = this.state.items.filter((item)=>/*ваш фильтр*/)
//ф-ю надо вынести в тело компонента, в рендере ей делать нечего
const onFilterClick = (e) => {
//должен просто устанавливать новый активный фильтр в стейте
this.setState({...this.state, filter: /*новое значение*/})
}
//в Items передаем уже отфильтрованные айтемы
return(
<div>
<Filters onFilterClick = { onFilterClick }/>
<Items items = {filteredItems} />
</div>
)
}
}
Кроме этого, вы зачем-то руками прописываете категории в компоненте Filters, но получаете их из вне в компоненте Shop. Вам нужно полученные в Shop фильтры передавать в компонент Filters и уже исходя из категорий делать кнопки. (это, кстати, упростит установку активного фильтра в Shop. См. пример.
export default class Shop extends Component {
KubicService = new Service()
state = {
items: {},
filters: {},
activeFilter: 'all' //в стейте теперь также находится текущий активный фильтр
}
//теперь ф-я получает не ивент, а новый активный фильтр
onFilterClick = (activeFilter) => {
this.setState({...this.state, filter: activeFilter})
}
componentDidMount() {/*ваш код*/}
render(){
const filteredItems = this.state.items.filter((item)=>/*ваш фильтр*/)
//Filters получает также и список имеющихся фильтров (categories)
return(
<div>
<Filters categories={this.state.filters} onFilterClick = { onFilterClick }/>
<Items items = {filteredItems} />
</div>
)
}
}
const Filters = (props) => {
return(
<div className='store-filters'>
<div className='filter-category'>
<div className='categories'>
{/*здесь получаете из props категории*/
props.categories.map(filter=>{
return <button onClick={()=>props.onFilterClick(filter) /*здесь устанавливаете новый фильтр при клике*/}>
{filter}
</button>
})
}
</div>
<select className="filter">
<option className='filter-variable'>Price: high to low</option>
<option className='filter-variable'>Price: low to high</option>
</select>
</div>
</div>
)
}