next.js 原因:`object`(“[object Date]”)不能序列化为JSON,请只返回JSON可序列化的数据类型

7vhp5slm  于 2023-04-20  发布在  其他
关注(0)|答案(5)|浏览(211)

我正在使用Prisma和Next.js。当我尝试在getStaticProps中从Prisma中检索内容时,它确实获取了数据,但我无法将其传递给主组件。

export const getStaticProps = async () => {
  const prisma = new PrismaClient();
  const newsLetters = await prisma.newsLetters.findMany();
  console.log(newsLetters);

  return {
    props: {
      newsLetters: newsLetters,
    },
  };
};

正如您在此图像中看到的,它正在获取和打印内容。

但是当我传递时,我得到了下面的错误,因为我把它作为props传递

Reason: `object` ("[object Date]") cannot be serialized as JSON. Please only return JSON serializable data types.
r6hnlfcb

r6hnlfcb1#

如果使用typescript,则不能将createdAt的类型更改为字符串或数字,如下所示:

newsLetter.createdAt = newsLetter.createdAt.toString();
// Error: Type 'string' is not assignable to type 'Date'.

相反,您可以在JSON.parse中使用JOSN.stringfy来创建可序列化对象:

export const getStaticProps = async () => {
  const prisma = new PrismaClient();
  const newsLetters = await prisma.newsLetters.findMany();

  return {
     props: {
        newsLetters: JSON.parse(JSON.stringify(newsLetters)) // <===
     }
  }
}
tyg4sfes

tyg4sfes2#

看起来nextJS不喜欢序列化任何东西,但出于性能原因,标量类型。你可以在这个github issue中阅读更多。处理这个问题的最好方法是在返回之前将Date对象转换为UNIX时间戳。

// your data
let newsLetters = [
    {
        id: 'your-id',
        email: 'email@example.com',
        createdAt: new Date()
    }
];

// map the array
newsLetters.map(x => {
    x.createdAt = Math.floor(x.createdAt / 1000);
    return x;
})

// use newsLetters now
console.log(newsLetters);
svmlkihl

svmlkihl3#

您可以使用Blitz's superjson package来实现此功能。https://github.com/blitz-js/superjson#using-with-nextjs:

配合Next.js使用

Next.js提供的getServerSidePropsgetInitialPropsgetStaticProps数据钩子不允许传输Dates等Javascript对象。除非将Dates转换为字符串等,否则会出错。
幸运的是,Superjson是一个完美的工具来绕过这个限制!

Next.js SWC Plugin(实验版,v12.2以上)

Next.js SWC插件是实验性的,但承诺显著加速。要使用SuperJSON SWC plugin,请安装它并将其添加到next.config.js

yarn add next-superjson-plugin
// next.config.js
module.exports = {
  experimental: {
    swcPlugins: [
      [
        'next-superjson-plugin',
        {
          excluded: [],
        },
      ],
    ],
  },
}
uinbv5nw

uinbv5nw4#

根据NextJS API Docs,getStaticProps return“应该是一个可序列化的对象,以便传递的任何props都可以用JSON. stringify序列化。
在Lodash isPlainObject test. www.example.com的文档https://lodash.com/docs/#isPlainObjectChecks中,这个函数声明“检查value是否是一个普通对象,也就是说,一个由Object构造函数创建的对象,或者一个Prototype为null的对象。”
下面的stack post讨论了两者的区别。
在@Viktor Kynchev答案的基础上,根据你对prop的需要,你可以把它转换成一个字符串,或者数字,或者Lodash的isPlainObject接受的其他类型。
对我来说,我有一个通过Prisma API提供的日期对象,就像OP一样,我只是把它转换成一个字符串。

for (const element of newsLetters) {
  element.createdAt = element.createdAt.toString()
}
p5fdfcr1

p5fdfcr15#

你可能在你的一个模型字段中有这个

createdAt DateTime @default(now())

date对象是不可序列化的.你可以使用date-fns npm module

import { formatDistance } from 'date-fns'

const newsLetters = await prisma.newsLetters.findMany();
const serializedNesLetters= newsLetters.map((newsLetter)=>({
     ...newsLetter, 
     createdAt:formatDistance(new Date(newsLetter.timestamp),new Date())
}))

这将返回以文字表示的给定日期之间的距离。
formatDistance docs

相关问题