Search code examples
javascriptreactjsreduxredux-toolkit

Why state in redux works this way?


cartSlice.js

import { createSlice } from "@reduxjs/toolkit";

const cartSlice = createSlice({
  name: 'items',
  initialState: {
    items: []
  },
  reducers: {
    addItem(state, action) {
      console.log(
        state.items.filter(item => item.id === action.payload.id)
      )
      console.log(
        state.items.filter(item => item.id === action.payload.id) != []
      )

      if (true) {
        let item = action.payload[0]
        let count = action.payload[1]
        state.items.push({ ...item, count })
      } else {
        console.log('asdas') //somelogic
      }
    },
    removeItem(state, action) {
      state.items = state.items.filter(item => item.id !== action.payload)
    }   
  }
});

export const { addItem, removeItem } = cartSlice.actions;
export default cartSlice.reducer;

Here is where I dispatch action:

import { React } from 'react'
import { addItem } from '/store/cartSlice'
import { useDispatch } from 'react-redux'
import { useState } from 'react'

export default function ProductPage() {
  let { state } = useLocation()
  let item = state.item
  const [count, setCount] = useState(1)
  const dispatch = useDispatch()

  const addTask = () => dispatch(addItem([item, count]))

  return (
    <>
      <div className={classes.info}>
        <h2 >{item.title}</h2>
        <span className={classes.price}>{item.price}</span>
        <div className={classes.quantity}>
          <button onClick={() => setCount(count - 1)}
          className={classes.quantityButton}>-</button>
          {count}
          <button onClick={() => setCount(count + 1)}
          className={classes.quantityButton}>+</button>
        </div> 
        <button className={classes.addToCartButton} 
        onClick={addTask}>Add to cart</button>
      </div>
    </>
  )
}

Here is console:

enter image description here

item is an object with keys title, id an some more. Why does the second log in addItem returns true and the first log returns an empty array in console?

I have only started working with Redux and don't understand how to work with state. I wanted to check if the item from action is actually in state.items but it isn't working as expected.


Solution

  • console log

    why does the second log in addItem returns true first log returns an empty array in console

    • The empty array of the first log is the result of state.items.filter(item => item.id === action.payload.id. action.payload is an array so the id property is undefined. The result array is empty because all item.id values are defined and not equal to undefined.

    • The second log outputs true because you are comparing two object references, one array/object reference isn't equal to another different array/object reference.

    Consider the following:

    const foo = [];
    const bar = foo;
    
    console.log("[] == []", [] == []);     // false
    console.log("[] != []", [] != []);     // true
    console.log("foo == bar", foo == bar); // true
    console.log("foo != bar", foo != bar); // false

    I wanted to check if the item from action is actually in state.items but it isn't working

    Update the reducer logic to correctly reference the passed item payload value.

    Examples:

    • Using the current array payload

      dispatch(addItem([item, count]))
      
      const [item, count] = action.payload;
      
      state.items.filter(el => el.id === item.id);
      
    • Using an object payload

      dispatch(addItem({ item, count }))
      
      const { item, count } = action.payload;
      
      state.items.filter(el => el.id === item.id);
      

    If you are trying to first check if state.items already contains the item you can search the array.

    Example:

    addItem(state, action) {
      const [item, count] = action.payload;
    
      const foundItem = state.items.find(el => el.id === item.id);
    
      if (foundItem) {
        // item found, update it
        ...
    
      } else {
        // item not found, add to state.items
        // maybe -> state.items.push({ ...item, count }) 🤷🏻‍♂️
        ...
    
      }
    },