larryfisherman
larryfisherman

Reputation: 35

How to don't overwrite Redux's state when dispatch

so I'm trying to dispatch a few objects and then display them. The problem is instead of adding new object to array, I'm overwriting them and it changes to a new one. So, I have a few products which are separate objects. I'm pushing them to an array and dispatching an array here:

function Product({ id, title, image, price, rating }) {
  const [items, setItems] = useState([]);
  const dispatch = useDispatch();

  useEffect(() => {
    dispatch(
      pushItems({
        items,
      })
    );
    console.log(items);
  }, [items]);

  return (
    <div className="product">
      <div className="product__Info">
        <p>{title}</p>
        <p className="product__Info__price">
          <small>$</small>
          <strong>{price}</strong>
        </p>
        <div className="product__Info__rating">
          {Array(rating)
            .fill()
            .map((_, i) => (
              <p>⭐</p>
            ))}
        </div>
      </div>
      <img src={image} alt="" />
      <button
        onClick={(e) =>
          setItems({
            title,
            image,
            price,
            rating,
          })
        }
      >
        Add to basket
      </button>
    </div>
  );
}

and that's how my reducer looks like, where I think the problem is:

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

const checkoutSlice = createSlice({
  name: "checkout",
  initialState: {
    items: null,
  },
  reducers: {
    pushItems: (state, action) => {
      state.items = [...state.items, action.payload.items];
    },
  },
});

export const { pushItems } = checkoutSlice.actions;
export const selectItems = (state) => state.checkout.items;

export default checkoutSlice.reducer;

I know how to do it in an "old way", but when I'm using slices I'm kinda confused.

Upvotes: 0

Views: 1075

Answers (1)

Shubham Khatri
Shubham Khatri

Reputation: 281686

Your Product component, doesn't need to store items array, you can directly update the items array in redux store

function Product({ id, title, image, price, rating }) {
  const dispatch = useDispatch();

  const onAddItem = (item) => {
      dispatch(pushItems({item}));
  }

  return (
    <div className="product">
      <div className="product__Info">
        <p>{title}</p>
        <p className="product__Info__price">
          <small>$</small>
          <strong>{price}</strong>
        </p>
        <div className="product__Info__rating">
          {Array(rating)
            .fill()
            .map((_, i) => (
              <p>⭐</p>
            ))}
        </div>
      </div>
      <img src={image} alt="" />
      <button
        onClick={(e) =>
          onAddItem({
            title,
            image,
            price,
            rating,
          })
        }
      >
        Add to basket
      </button>
    </div>
  );
}

Also note that state updation inside redux-toolkit slice doesn't need to take care of immutability as it internally used immer.

You can update your redux state like below:

const checkoutSlice = createSlice({
  name: "checkout",
  initialState: {
    items: null,
  },
  reducers: {
    pushItems: (state, action) => {
      state.items.push(action.payload.item);
    },
  },
});

Upvotes: 2

Related Questions