Next.js Typescript从对象Map数组

flvtvl50  于 5个月前  发布在  TypeScript
关注(0)|答案(1)|浏览(47)

我需要Map下面的对象,如{ ...product.images[0] }{ ...product.type[0] }{ ...product.productPackages[0] },在我下面的代码。
这是我的目标:

export const customImage = [
  {
    status: false,
    image: null,
    price: 10,
  },
];

字符串
我进口了这个

import { customImage } from "@/utils/customImage";


但当前声明是错误的。[this one selectedCustomImage: customImage,](我得到了下面的错误这个Map)
类型“{状态:boolean;图片:无效;价格:数量;}[]“缺少类型”SelectedCustomImageType“中的以下属性:status、image、pricets(2739)
(属性)selectedCustomImage:SelectedCustomImageType
请帮助我正确Map这个数组。
这是我的代码:

"use client";
import { useCart } from "@/hooks/useCart";
import { customImage } from "@/utils/customImage";
import { formatPrice } from "@/utils/formatprice";
import { Rating } from "@mui/material";
import { useRouter } from "next/navigation";
import { useCallback, useEffect, useState } from "react";
import { MdCheckCircle } from "react-icons/md";
import toast from "react-hot-toast";
import Button from "@/app/components/Button";
import CustomImageInput from "@/app/components/inputs/CustomImageInput";
import PackageButton from "@/app/components/inputs/PackageButton";
import ProductImage from "@/app/components/products/ProductImage";
import SetQuantity from "@/app/components/products/SetQuantity";
import TypeImage from "@/app/components/products/TypeImage";
import SetColor from "@/app/components/products/setColor";
import SetType from "@/app/components/products/setType";

interface ProductDetailsProps {
  product: any;
}

export type CartProductType = {
  id: string;
  name: string;
  description: string;
  category: string;
  brand: string;
  selectedImg: SelectedImgType;
  selectedProduct: SelectedProductType;
  quantity: number;
  selectedPackage: SelectedPackageType;
  price: number;
  productPrice: number;
  file: any;
  selectedCustomImage: SelectedCustomImageType;
};
// customImagePrice: number;

export type SelectedImgType = {
  color: string;
  colorCode: string;
  image: string;
};

export type SelectedProductType = {
  type: string;
  typeCode: string;
  typePrice: number;
  image: string;
};

export type SelectedPackageType = {
  packaging: string;
  price: number;
  image: string;
};

export type SelectedCustomImageType = {
  status: boolean;
  image: string;
  price: number;
};

export type CustomImage = {
  status: boolean;
  image: File | null;
  price: number;
};

const Horizontal = () => {
  return <hr className="w-[30% my-2]" />;
};

const ProductDetails: React.FC<ProductDetailsProps> = ({ product }) => {
  const router = useRouter();

  const { handleAddProductToCart, cartProducts } = useCart();

  const [isProductInCart, setIsProductInCart] = useState(false);

  const [cartProduct, setCartProduct] = useState<CartProductType>({
    id: product.id,
    name: product.name,
    description: product.description,
    category: product.category,
    brand: product.brand,
    selectedImg: { ...product.images[0] },
    selectedProduct: { ...product.type[0] },
    quantity: 1,
    price: product.price,
    productPrice: product.price,
    selectedPackage: { ...product.productPackages[0] },
    file: null,
    selectedCustomImage: customImage,
  });

  useEffect(() => {
    setIsProductInCart(false);

    if (cartProducts) {
      const existingIndex = cartProducts.findIndex(
        (item) => item.id === product.id,
      );

      if (existingIndex > -1) {
        setIsProductInCart(true);
      }
    }
  }, [cartProducts]);

  const productrating =
    product.reviews.reduce((acc: number, item: any) => item.rating + acc, 0) /
    product.reviews.length;

  const handleColorSelect = useCallback(
    (value: SelectedImgType) => {
      setCartProduct((prev) => {
        return { ...prev, selectedImg: value };
      });
    },
    [cartProduct.selectedImg],
  );
  const handleCustomImageSelect = useCallback(
    (value: SelectedProductType) => {
      setCartProduct((prev) => {
        if ((cartProduct.file = null)) {
        }
        return {
          ...prev,
          selectedProduct: value,
          price: product.price,
          productPrice: value.typePrice * cartProduct.quantity,
          customImagePrice: value.typePrice * cartProduct.quantity,
        };
      });
    },
    [cartProduct.selectedProduct],
  );
  const handleTypeSelect = useCallback(
    (value: SelectedProductType) => {
      setCartProduct((prev) => {
        return {
          ...prev,
          selectedProduct: value,
          price: product.price,
          productPrice: value.typePrice * cartProduct.quantity,
          customImagePrice: value.typePrice * cartProduct.quantity,
        };
      });
    },
    [cartProduct.selectedProduct],
  );

  const handlePackageSelect = useCallback(
    (value: SelectedPackage) => {
      setCartProduct((prev) => {
        return {
          ...prev,
          selectedPackage: value,
          price: product.price,
          productPrice: value.price * cartProduct.quantity,
          customImagePrice: value.price * cartProduct.quantity,
        };
      });
    },
    [cartProduct.selectedProduct],
  );

  const handleQtyIncrease = useCallback(() => {
    if (cartProduct.quantity === 99) {
      return;
    }

    setCartProduct((prev) => {
      return { ...prev, quantity: ++prev.quantity };
    });
  }, [cartProduct]);

  const handleQtyDecrease = useCallback(() => {
    if (cartProduct.quantity === 1) {
      return;
    }

    setCartProduct((prev) => {
      return { ...prev, quantity: --prev.quantity };
    });
  }, [cartProduct]);
  //console.log("this is cart product >>>>", cartProduct);

  const [images, setImages] = useState<CustomImage[] | null>();

  const addImageToState = useCallback((value: CustomImage) => {
    setImages((prev) => {
      if (!prev) {
        return [value];
      }
      return [...prev, value];
    });
  }, []);

  const removeImageFromState = useCallback((value: CustomImage) => {
    setImages((prev) => {
      if (prev) {
        const filteredImages = prev.filter((item) => item.price != value.price);
        return filteredImages;
      }
      return prev;
    });
  }, []);

  const [isProductCreated, setIsProductCreated] = useState(false);
  return (
    <div>
      <div>
        {" "}
        <div className="grid grid-cols-1 md:grid-cols-2 gap-12">
          <ProductImage
            cartProduct={cartProduct}
            product={product}
            handleColorSelect={handleColorSelect}
          />
          <div className="flex flex-col gap-1 text-slate-700 text-sm">
            <h2 className="text-3xl font-medium text-slate-700">
              {product.name}
            </h2>
            <div className="flex items-center gap-2">
              <Rating value={productrating} readOnly />
              <div>{product.reviews.length} reviews</div>
            </div>
            <Horizontal />
            <div className="text-justify">{product.description}</div>
            <Horizontal />
            <div>
              <span className="font-semibold">CATEGORY : </span>
              {product.category}
            </div>
            <div>
              <span className="font-semibold">BRAND : </span>
              {product.brand}
            </div>
            <div
              className={
                product.availablequantity > 0
                  ? "text-teal-400"
                  : "text-rose-400"
              }
            >
              {product.availablequantity > 0 ? "In Stock" : "Out of Stock"}
            </div>
            <Horizontal />
            {isProductInCart ? (
              <>
                <p className="mb-2 text-slate-500 flex items-center gap-1">
                  <MdCheckCircle className="text-teal-400" size={20} />
                  <span>Product added to Cart</span>
                </p>
                <div className="max-w-[300px]">
                  <Button
                    label="View Cart"
                    outline
                    onClick={() => {
                      router.push("/cart");
                    }}
                  />
                </div>
              </>
            ) : (
              <>
                <div>
                  <span className="font-semibold">TYPE : </span>
                  <TypeImage
                    cartProduct={cartProduct}
                    product={product}
                    handleTypeSelect={handleTypeSelect}
                  />
                  <SetType
                    cartProduct={cartProduct}
                    type={product.type}
                    handleTypeSelect={handleTypeSelect}
                  />
                </div>
                <Horizontal />
                <SetColor
                  cartProduct={cartProduct}
                  images={product.images}
                  handleColorSelect={handleColorSelect}
                />
                <Horizontal />
                <SetQuantity
                  cartProduct={cartProduct}
                  handleQtyIncrease={handleQtyIncrease}
                  handleQtyDecrease={handleQtyDecrease}
                />
                <Horizontal />
                <div>
                  <div className="justify-self-end font-semibold">
                    <span className="font-semibold">PRICE : </span>
                    {formatPrice(product.price)}
                  </div>
                </div>
                <Horizontal />
                <div>
                  <div className="justify-self-end font-semibold">
                    <span className="font-semibold">Packaging : </span>
                    {/** Add packaging type here grid grid-cols-2 gap-4 max-w-[300px] mt-6 mb-6*/}
                  </div>
                  <div className="">
                    <PackageButton
                      handlePackageSelect={handlePackageSelect}
                      cartProduct={cartProduct}
                      product={product}
                      label={product.productPackages}
                      price={[]}
                    />
                  </div>
                </div>
                <Horizontal />
                <div>
                  <div className="justify-self-end">
                    <span className="font-semibold">Custom Image : </span>
                    <div className="w-full flex flex-col flex-wrap gap-4">
                      <div>
                        <div className="font-bold subpixel-antialiased">
                          Add your company logo, name or any other custom image
                          which should be printed on your product.
                        </div>
                        <div className="text-sm italic mt-1">
                          Additional charges apply!
                        </div>
                      </div>
                      <div className="grid grid-cols-2 gap-3">
                        {customImage.map((item, index) => {
                          return (
                            <CustomImageInput
                              key={index}
                              item={item}
                              addImageToState={addImageToState}
                              removeImageFromState={removeImageFromState}
                              isProductCreated={isProductCreated}
                              cartProduct={cartProduct}
                              setCartProduct={setCartProduct}
                              handleCustomImageSelect={handleCustomImageSelect}
                            />
                          );
                        })}
                      </div>
                    </div>
                  </div>
                  <div>{/* add image upload here */}</div>
                </div>
                <div>
                  <div className="justify-self-end font-semibold">
                    <span className="font-semibold">Total: </span>
                    {/* {cartProduct.isCustomImage
                          ? formatPrice(
                              cartProduct.productPrice * cartProduct.quantity +
                                cartProduct.selectedPackage.price *
                                  cartProduct.quantity
                            )
                          : formatPrice(
                              cartProduct.productPrice * cartProduct.quantity +
                                cartProduct.selectedPackage.price *
                                  cartProduct.quantity +
                                cartProduct.customImagePrice
                            )} */}
                    {/* {formatPrice(
                          cartProduct.productPrice * cartProduct.quantity + cartProduct.selectedPackage.price *cartProduct.quantity)} */}
                    {formatPrice(
                      (cartProduct.productPrice =
                        (cartProduct.price +
                          cartProduct.selectedProduct.typePrice +
                          cartProduct.selectedPackage.price) *
                        cartProduct.quantity),
                    )}

                    <span className="font-semibold">
                      Type: {cartProduct.selectedProduct.typePrice}
                    </span>
                    <span className="font-semibold">
                      Package: {cartProduct.selectedPackage.price}
                    </span>
                  </div>
                </div>
                <div className="max-w-[300px] ">
                  <Button
                    label="Add To Cart"
                    onClick={() => handleAddProductToCart(cartProduct)}
                  />
                </div>
              </>
            )}
          </div>
        </div>
      </div>
    </div>
  );
};

export default ProductDetails;

ctehm74n

ctehm74n1#

看起来使用的对象应该是一个数组,你只是忘记了在这里索引它:

selectedPackage: { ...product.productPackages[0] },
    file: null,
    selectedCustomImage: customImage[0],

字符串
你还必须赋值一个空字符串而不是null。

export const customImage = [
  {
    status: false,
    image: '',
    price: 10,
  },
];


如果对象不需要是数组,请删除方括号:

export const customImage =
  {
    status: false,
    image:'',
    price: 10,
  };


然后完全删除map调用

<div className="grid grid-cols-2 gap-3">
  <CustomImageInput
    item={customImage}

相关问题