Search code examples
reactjstypescriptzustand

Pass data to a cart page as a object with multiple values - state management


I'd like to pass a data i.e. id, title to a cart page as array of objects, but Typescript screaming at me that I did sth wrong, but i don't know what.

error(1):

Argument of type '(state: CartState) => { carts: (string | SugarProductSchema)[]; }' is not assignable to parameter of type 'CartState | Partial | ((state: CartState) => CartState | Partial)'. Translation: I was expecting CartState | Partial | ((state: CartState) => CartState | Partial), but you passed (state: CartState) => { carts: (string | SugarProductSchema)[]; }

// zustand state management store

import create from 'zustand';
import { devtools, persist } from 'zustand/middleware';
import { SugarProductSchema } from '@/types/sugar-product-schema';

interface CartState {
  carts: SugarProductSchema[];
  addToCart: (id: string, title: string) => void;
}

const useCartStore = create<CartState>()(
  devtools(
    persist(
      (set) => ({
        carts: [],
        addToCart: (id, title) =>
          set((state) => ({ carts: [...state.carts, id, title] })), // here is the error(1)
      }),
      {
        name: 'cart-storage',
      }
    )
  )
);

export default useCartStore;

product card component:

// (...) 
const addToCart = useCartStore((state) => state.addToCart);

  const handleCartProducts = () => {
    addToCart(id, title);
    toast.success('Dodano produkt do koszyka');
    console.log(id);
  };
// (...) 

Right now, it shows that error(1) which is mentioned above, but it still saves the data: e.g. id and title but in the way I don't want to: It's generating one array and adding values to this array instead of creating objects with id and title e.g.

enter image description here

it should like this:

[
 //product 1 {id:"t512521512", title:"random title"}
 //product 2 {id:"xxxxxx", title:"randosasasam title"}
//and so on

]

SugarProductSchema type file

export type SugarProductSchema = {
  title: string;
  brand: string;
  price: number;
  coverImage: string;
  id: string;
  slug: string;
};


Solution

  • So I would guess the issue is that

    set((state) => ({ carts: [...state.carts, id, title] }))
    

    Isn't quite what you were wanting. You'll end up with something like

    { carts: [ cart1, cart2, cart3, id, title] }
    

    Whereas that set function wants an array of SugarProductSchema and you're giving it (string | SugarProductSchema)[]. It's the rogue strings of id and title that are throwing it off.

    Maybe what you're looking for is

    set((state) => ({ carts: [ ...state.carts, { id, title } ] })
    

    But then you're missing several fields from SugarProductSchema and it will be angry about that too. The main idea here is that the carts field in your CartState needs to be an array of SugarProductSchema types and nothing else.

    If you just want the id and title to be required you might consider making the other fields in SugarProductSchema optional. Like

    export type SugarProductSchema = {
      title: string;
      brand?: string;
      price?: number;
      coverImage?: string;
      id: string;
      slug?: string;
    };
    

    If they need to be required then you'll need to add those fields in when using set