序列化从`getStaticProps`返回的`.product`时出错|使用NextJS和Stripe

a11xaf1n  于 2023-08-04  发布在  其他
关注(0)|答案(2)|浏览(82)

我遇到了以下错误“错误:序列化从“/products/[id]”中的getStaticProps返回的.product时出错。原因:undefined不能序列化为JSON。请使用null或省略此值。”
当我尝试为我的电子商务网站创建单独的产品页面时,就发生了这种情况。
我在“/products/[id]”中的代码

import Image from "next/image";
import { stripe } from "src/utils/stripe";
import { CheckIcon, MinusSmallIcon, PlusSmallIcon } from "@heroicons/react/24/solid"
import { formatCurrencyString, useShoppingCart } from "use-shopping-cart";
import { useState } from "react";
import { toast } from "react-hot-toast";

export default function ProductPage({ product }) {
    const [count, setCount] =  useState(1);
    const { addItem } = useShoppingCart()

    function onAddToCart(event) {
        event.preventDefault();
        const id = toast.loading("Adding 1 item...");
        addItem(product);
        toast.success(product.name, { id });
    }

    return (
        <div className="container lg:max-w-screen-lg mx-auto py-12 px-6">
            <div className="flex flex-col md:flex-row justify-between items-center space-y-8 md:space-y-0 md:space-x-12">
                <div className="relatie w-72 h-72 sm:w-96 sm:h-96">
                    <Image src={product.image} alt={product.name} fill style={{objectFit: "contain" }} sizes="100%" priority />
                </div>

                <div className="w-full flex-1 max-w-md border border-opacity-50 rounded-md shadow-lg p-6 bg-whitie">
                    <h2 className="text-3x1 font-semibold">{product.name}</h2>
                    <p className="pt-2 flex items-center space-x-2">
                        <CheckIcon className="text-lime-500 w-5 h-5" />
                        <span className="font-semibold">In stock</span>
                    </p>

                    <div className="mt-4 border-t pt-4">
                        <p className="text-gray-500">Price: </p>
                        <p className="text-xl front-semibold">{formatCurrencyString({ value: product.price, currency: product.currency,})} </p>
                    </div>

                    <div className="mt-4 border-t pt-4">
                        <p className="text-gray-500">Quantity</p>
                        <div className="mt-1 flex items-center space-x-3">
                            <button disabled={count <= 1} onClick={() => setCount(count - 1)} className="p-1 rounded-md hover:bg-rose-100 hover:text-rose-500">
                                <MinusSmallIcon className="w-6 h-6 flex-shrink-0"/>
                            </button>
                            <p className="font-semibold text-xl">{count}</p>
                            <button onAbort={() => setCount(count + 1)} className="p-1 rounded-md hover:bg-green-100 hover:text-green-500">
                                <PlusSmallIcon className="w-6 h-6 flex-shrink-0"/>
                            </button>
                        </div>
                    </div>

                    <button className="w-full mt-4 border border-lime-500 py-2 px-2 bg-lime-500 hover:bg-lime-600 hover:border-lime-600 focus:ring-4 focus:ring-opacity-50 focus:ring-lime-500 text-white disabled:opacity-50 disabled:cursor-not-allowed rounded-md">
                        Add to cart
                    </button>
                </div>
            </div>
        </div>
        );
}

export async function getStaticPaths() {
    const inventory = await stripe.products.list();
    const paths = inventory.data.map((product) => ({
        params: { id: product.id },
    }));

    return {
        paths, 
        fallback: "blocking"
    };
}

export async function getStaticProps({ params }) {
    const inventory = await stripe.products.list({
        expand: ["data.default_price"],
    });
    const products = inventory.data.map((product) => {
        const price = product.default_price;
        return {
          currency: price.currency,
          id: product.id,
          name: product.name,
          price: price.unit_amount,
          image: product.images[0],
        };
    });
    const product = products.find((product) => product.id === params.id);

    return {
        props: {
            product,
        },
        revalidate: 60 * 60,
    };
}

字符串
我已经研究了一些建议JSON.parse(JSON.stringify(“string”))的解决方案。这一招没用。
我也从blackbox得到了这个,但是函数已经是异步的,当调用getStaticProps函数时,product变量仍然是未定义的。这是因为stripe.products.list()函数是异步的,而getStaticProps函数是同步的。

x6h2sr28

x6h2sr281#

可能发生的情况是,您的products.find实际上并没有将任何产品与params.id匹配。这会导致product未定义,然后NextJS不喜欢你在props中有一个未定义的值。
有几种方法可以解决这个问题,这取决于你需要什么:
1.也许NextJS处理这个问题的最好方法是,如果没有找到product,则返回notFound: true而不是props,从而导致404页面

if (!product) {
        return {
            notFound: true
        };
    }

字符串
1.如果未找到product,则返回undefined以外的值:

return {
        props: {
            product: product ?? null,
        },
        revalidate: 60 * 60,
    };


或者,除非定义了产品属性,否则不要添加它

return {
        props: {
            ...(product && { product }),
        },
        revalidate: 60 * 60,
    };


如果您的客户端设置为处理缺少product的情况,则仅使用#2。

kmynzznz

kmynzznz2#

听起来像products可能是null。Optional chaining可以帮助:

- const products = inventory.data.map((product) => {
+ const products = inventory?.data?.map((product) => {

字符串

相关问题