N
N
nivaech2019-12-11 08:34:40
JavaScript
nivaech, 2019-12-11 08:34:40

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('');
...
...

2. Below are the functions that are responsible for changing the array (filtered elements) and the filter by color function.
// ---------------------- 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();
    };

3. As a result, filteredItems is mapped and displays the items.
<div className="items">
                    {
                        filteredItems.map(item => (
                            <ProductCard 
                                key={item.id} 
                                item={item} 
                                defineSingle={defineSingle}
                            />
                        ))
                    }
</div>

4. This is what the filter component looks like. The function maps the colors specified in the database and displays them in the panel. When a color is clicked, the filterByColor(color) function fires, which puts the selected color into the state, and then calls the sortItems() function, which should take the filter value and render a new array, already filtered.
<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>

Everything works, but only after the second click on the color value in the filter. What's wrong?
UPD: It seems that the problem is that on clicking on a color, its value is sent to setColorFIlter not immediately upon clicking, and that the problem is in it. But the problem has not yet been resolved.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
N
nivaech, 2019-12-11
@nivaech

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])

3. Rewrite the sortItems() function itself, taking into account the useCallback hook:
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])

And everything works

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question