Answer the question
In order to leave comments, you need to log in
Why does the filter work only after the second click?
There is a color filter. By clicking on a certain color, its value is entered into the state, and then using the array filter, the corresponding elements should be displayed. But the problem is that the filter works only after the second click, and not immediately.
1. An array of data is loaded into the component and stored in filteredItems. Here are the state values:
const Products = ({ collection, indiVisible, match }) => {
const { items } = collection;
useEffect(() => {
let tempItems = [...items]
setFilteredItems(tempItems)
}, [items])
// ---------------------- Defining states
const [ filteredItems, setFilteredItems ] = useState(items);
const [ colorFilter, setColorFIlter ] = useState('');
...
...
// ---------------------- Sort items
const sortItems = () => {
let tempItems = [...items];
// -----> Filter by colors
if (colorFilter) {
tempItems = tempItems.filter(item => item.color.includes(colorFilter));
}
setFilteredItems(tempItems);
}
// ---------------------- Filter Item by color
const filterByColor = (color) => {
setColorFIlter(color);
console.log(`now color is ${color}`)
sortItems();
};
<div className="items">
{
filteredItems.map(item => (
<ProductCard
key={item.id}
item={item}
defineSingle={defineSingle}
/>
))
}
</div>
<ul className={`filter-list ${colorFilter && "opened-filter"}`}>
{
colors.map((color, index) => (
<li className="filter-item color-filter" key={index} onClick={() => filterByColor(color)}>
<div className="color-ball" style={{ backgroundColor: color }} />
{color}
</li>
))
}
<button className="btn" onClick={dropColorFIlter}>Clear</button>
</ul>
Answer the question
In order to leave comments, you need to log in
The problem was solved.
1. Instead of passing the filter component to the filterByColor() function, you should have passed setColorFIlter directly with
useState.
2. Add a new effect that reacts to state changes and calls the sortItems() sorting function
useEffect(() => {
if (setColorFilter) {
sortItems()
}
}, [colorFilter, sortItems])
const sortItems = useCallback(() => {
let tempItems = [...items];
// -----> Filter by colors
if (colorFilter) {
tempItems = tempItems.filter(item => item.color.includes(colorFilter));
}
setFilteredItems(tempItems);
console.log(`items are sorted. new array has ${tempItems.length} items`)
}, [colorFilter, items])
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question