P
Prisma13mo ago
martink

Working with decimal in NextJS

Has anyone found a reasonable way to work with Decimal in NextJS? "Only plain objects can be passed to Client Components from Server Components. Decimal objects are not supported." Every time we add a Decimal to our schema, we end up breaking a bunch of server components. The only option seems to be manually serializing and deserializing everything, which isn't great. Is there a way to tell NextJS or Prisma to serialize our Decimals as strings when sending to and from the client? Or are there other recommendations on how to work with decimals?
5 Replies
RaphaelEtim
RaphaelEtim13mo ago
Hi @martink This is an issue that has been encountered by most users. One user suggested this workaround in this issue .
GitHub
Option to disable Decimal.js Generation? · Issue #6049 · prisma/pri...
Problem I have few columns in my db that have Decimal values, my GraphQL Server usually returns whatever responses that Prisma returns (using Float in GraphQL for Decimals). Recently I upgraded to ...
martink
martinkOP13mo ago
Ah thanks - I tried that (and a custom .$extends) and it seems to work, but I still get errors: Only plain objects can be passed to Client Components from Server Components. Decimal objects are not supported. or Only plain objects can be passed to Client Components from Server Components. Objects with symbol properties like nodejs.util.inspect.custom are not supported. respectively
martink
martinkOP13mo ago
GitHub
Computed fields (via Client Extensions) are producing non-POJOs · I...
Problem If I'm using computed fields in SvelteKit - objects can't be serialized by devalue() because they are not passing POJO check. E.g. const prismax = prisma.$extends({ result: { user: ...
martink
martinkOP13mo ago
It's looking to me like the solution is really just not to use Decimal and use a fixed int type instead? e.g. "cents" or whatever precision I need?
Luigi
Luigi3w ago
I tried the suggested hack but still got the 'Decimal object to client' error. I found a workaround—converting decimals to numbers in every operation. It's not ideal, but it’s the only solution that worked without errors:
import { Prisma, PrismaClient } from "@/app/generated/client";

function convertDecimals(obj: any): any {
if (obj === null || obj === undefined) return obj;

if (obj instanceof Prisma.Decimal) {
return obj.toNumber();
}

if (Array.isArray(obj)) {
return obj.map(convertDecimals);
}

if (typeof obj === "object") {
const converted: any = {};
for (const key in obj) {
converted[key] = convertDecimals(obj[key]);
}
return converted;
}

return obj;
}

const globalForPrisma = global as unknown as {
prisma: ReturnType<typeof createPrismaClient>;
};

function createPrismaClient() {
const client = new PrismaClient({
log: ["query"],
});

return client.$extends({
query: {
$allModels: {
async $allOperations({ operation, model, args, query }) {
const result = await query(args);
return convertDecimals(result);
},
},
},
});
}

const prisma = globalForPrisma.prisma || createPrismaClient();

if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;

export default prisma;
import { Prisma, PrismaClient } from "@/app/generated/client";

function convertDecimals(obj: any): any {
if (obj === null || obj === undefined) return obj;

if (obj instanceof Prisma.Decimal) {
return obj.toNumber();
}

if (Array.isArray(obj)) {
return obj.map(convertDecimals);
}

if (typeof obj === "object") {
const converted: any = {};
for (const key in obj) {
converted[key] = convertDecimals(obj[key]);
}
return converted;
}

return obj;
}

const globalForPrisma = global as unknown as {
prisma: ReturnType<typeof createPrismaClient>;
};

function createPrismaClient() {
const client = new PrismaClient({
log: ["query"],
});

return client.$extends({
query: {
$allModels: {
async $allOperations({ operation, model, args, query }) {
const result = await query(args);
return convertDecimals(result);
},
},
},
});
}

const prisma = globalForPrisma.prisma || createPrismaClient();

if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;

export default prisma;

Did you find this page helpful?