Unable to filter out redux state based on values from another local state

So I have this API data, which is being stored in redux store. The first element in the redux state data is then used in useEffect to set a local state used in the initial render. Now in a button click handler function, I’m trying to use that local state to filter out the data from redux state. Then the first element from filtered data should be pushed to the local state.

I’ll explain the code here. Suppose I’m getting the API data from redux store like this:

const categoriesState = useSelector( state => state.getCats );
const { categories } = categoriesState;

Then in useEffect I use the first element from categories to be stored in a local state:

const [ catItems, setCatItems ] = useState( [] );

useEffect(() => {
     
     if ( categories && categories.length !== 0 ) {
           setCatItems( [ categories[ 0 ] ] );
     }    

}, [] );

catItems is then used to render something. But there is also a button that, upon clicking, will add a new category to catItems from categories state but leave out the item which is already in it.

Here’s the click handler:

const handleAddCat = ( e ) => {

        if ( categories && categories.length !== 0 ) {

              const catCopy = [ ...catItems ];

              const filterCategories = categories.filter( item => {
                   for ( let el of catCopy ) {
                        return item.category !== el.category;
                   }
              });

              catCopy.push( filterCategories[ 0 ] );

              setCatItems( catCopy );

        }
}

On the first click, the filter works perfectly. But on the second button click, I get the same data. For example, if the local state’s initial data is 1, then on the first button click, I get both 1 and 2. But on second button click I get 1, 2 and 2. 2 is being added on subsequent clicks. Whereas, 2 should be filtered out. Then 3, then 4 and so on.

What am I doing wrong here?

Answer

You can just find the mismatched category instead of ( creating the filterCategories and then picking the first one ). Here is the implementation.

const handleAddCat = ( e ) => {

  if ( categories && categories.length !== 0 ) {
    const newCategory = categories.find(category => !cat.includes(category));
    if(newCategory) setCatItems((prevItems) => [...prevItems, newCategory]);

  }
}