Why the filter only works after the second click?

There is a filter in color. By clicking on a specific color, its value is logged in state and then with the filter array must check the corresponding items. But the problem is that the filter only works after the second button, but not immediately.
1. The component is loaded in the data array and stored in filteredItems. Then the values of the state:
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. The following are the functions that are responsible for changes of the array (filtered elements) and a function of filter color.
// ---------------------- 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. Eventually mapitse filteredItems and displays the items.
<div className="items">
{
 filteredItems.map(item => (
 <ProductCard 
 key={item.id} 
 item={item} 
defineSingle={defineSingle}
/>
))
}
</div>

4. It looks like the filter component. Function MapIT colors defined in the database, and displays them in the panel. Click on the color function operates filterByColor(color), which puts the selected color in the state, and then calls the function sortItems(), which should take the filter value and render a new array that is 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>


It 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 the color its value is sent to setColorFIlter not immediately pressing, and that the problem is in it. But the problem is not yet resolved.
April 3rd 20 at 17:24
1 answer
April 3rd 20 at 17:26
Solution
The problem was solved.
1. Instead of passing a component of a filter function filterByColor() had to be negotiated directly with setColorFIlter
useState.
2. Add a new effect, reacting to changing state and calling the sorting function sortItems()
useEffect(() => {
 if (setColorFilter) {
sortItems()
}
 }, [colorFilter, sortItems])

3. The function sortItems() to rewrite the given hook useCallback:
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

Find more questions by tags JavaScriptReact