W
Wasp2w ago
4jandals

Best way to generate null form values for a Prisma update

Not sure best place to ask this question, but I figure developers building CRUD forms in wasp might have the same question. I have an entity like this:
model Foo {
id String @id @default(uuid(7))
bar String?
}
model Foo {
id String @id @default(uuid(7))
bar String?
}
I'm updating the entity like this in the back-end:
export const updateFoo: UpdateFoo<{
id: string;
bar?: string;
}, Foo> = async ({ id, ...updatedData }, context) => {

if (!context.user) {
throw new HttpError(401, 'Not authorized');
}

const updated = await context.entities.Foo.update({
where: {
id,
},
data: {
updatedData,
}
});
export const updateFoo: UpdateFoo<{
id: string;
bar?: string;
}, Foo> = async ({ id, ...updatedData }, context) => {

if (!context.user) {
throw new HttpError(401, 'Not authorized');
}

const updated = await context.entities.Foo.update({
where: {
id,
},
data: {
updatedData,
}
});
I have a Zod schema in the front-end code
formSchema = z
.object({
title: z.string().optional().nullable()
})
formSchema = z
.object({
title: z.string().optional().nullable()
})
In my form if I clear the value of bar it generates the following for updatedData:
{
bar: undefined
}
{
bar: undefined
}
As a result bar will be ignored in the Prisma update and so it doesn't clear to null. What's best practise here?: 1. Do I need to find a way to get Zod to generate null for empty fields (I've tried) 2. Or do I need to convert fields that are undefined to null in the updatedData object before using Prisma to update the object. I've read this https://www.prisma.io/docs/orm/prisma-client/special-fields-and-types/null-and-undefined which indicates that undefined should be avoided in Primsa.
4 Replies
kapa.ai
kapa.ai2w ago
Hi @4jandals. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Based on the knowledge sources and your question about handling null values in Prisma updates with Wasp, I can provide some guidance. Your issue is a common one when working with Prisma - undefined values are ignored in updates, which means empty form fields don't clear to null as expected. According to the Prisma documentation you referenced, undefined values should indeed be avoided in Prisma operations. Looking at your options: 1. Converting undefined to null in your action before passing to Prisma is the recommended approach. This aligns with Prisma's documentation and would ensure your empty fields are properly set to null. 2. While you could try to make Zod generate null instead of undefined, handling this transformation in your action provides more control and follows Prisma best practices. In your action, you could implement something like:
export const updateFoo: UpdateFoo<{
id: string;
bar?: string;
}, Foo> = async ({ id, ...updatedData }, context) => {

if (!context.user) {
throw new HttpError(401, 'Not authorized');
}

// Convert undefined values to null
const processedData = Object.fromEntries(
Object.entries(updatedData).map(([key, value]) => [key, value === undefined ? null : value])
);

const updated = await context.entities.Foo.update({
where: {
id,
},
data: processedData
});

return updated;
}
export const updateFoo: UpdateFoo<{
id: string;
bar?: string;
}, Foo> = async ({ id, ...updatedData }, context) => {

if (!context.user) {
throw new HttpError(401, 'Not authorized');
}

// Convert undefined values to null
const processedData = Object.fromEntries(
Object.entries(updatedData).map(([key, value]) => [key, value === undefined ? null : value])
);

const updated = await context.entities.Foo.update({
where: {
id,
},
data: processedData
});

return updated;
}
This approach is consistent with how Wasp handles Prisma operations. The Wasp team is aware of some limitations in the current CRUD implementations and is planning improvements for validation and data handling in the future, as mentioned in the CRUD documentation. Also note that there's an open issue about improving CRUD operations default implementations in Wasp, which might address these kinds of challenges in the future: GitHub Issue #1253. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @4jandals, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist: Perhaps try again in 15mins?
Carlos
Carlos2w ago
the zod schema sounds like a good place to generate the nulls, this is a simple way of doing that:
const formSchema = z.object({
title: z
.string()
.nullish() // allows undefined and null
.transform((val) => val ?? null), // turns nullish values to regular null
});
const formSchema = z.object({
title: z
.string()
.nullish() // allows undefined and null
.transform((val) => val ?? null), // turns nullish values to regular null
});
btw, html forms usually generate an empty string "" as a way to have an empty field, you could then modify the schema like this:
const formSchema = z.object({
title: z
.string()
.nullish() // allows undefined and null
.transform((val) => val || null), // turns falsy values to null
});
const formSchema = z.object({
title: z
.string()
.nullish() // allows undefined and null
.transform((val) => val || null), // turns falsy values to null
});
with the first option:
┌───────┬──────────────────────┬────────────────────┐
│ (idx) │ input │ output │
├───────┼──────────────────────┼────────────────────┤
│ 0 │ {} │ { title: null } │
│ 1 │ { title: null } │ { title: null } │
│ 2 │ { title: undefined } │ { title: null } │
│ 3 │ { title: "" } │ { title: "" } │
│ 4 │ { title: "hello" } │ { title: "hello" } │
└───────┴──────────────────────┴────────────────────┘
┌───────┬──────────────────────┬────────────────────┐
│ (idx) │ input │ output │
├───────┼──────────────────────┼────────────────────┤
│ 0 │ {} │ { title: null } │
│ 1 │ { title: null } │ { title: null } │
│ 2 │ { title: undefined } │ { title: null } │
│ 3 │ { title: "" } │ { title: "" } │
│ 4 │ { title: "hello" } │ { title: "hello" } │
└───────┴──────────────────────┴────────────────────┘
with the second option:
┌───────┬──────────────────────┬────────────────────┐
│ (idx) │ input │ output │
├───────┼──────────────────────┼────────────────────┤
│ 0 │ {} │ { title: null } │
│ 1 │ { title: null } │ { title: null } │
│ 2 │ { title: undefined } │ { title: null } │
│ 3 │ { title: "" } │ { title: null } │
│ 4 │ { title: "hello" } │ { title: "hello" } │
└───────┴──────────────────────┴────────────────────┘
┌───────┬──────────────────────┬────────────────────┐
│ (idx) │ input │ output │
├───────┼──────────────────────┼────────────────────┤
│ 0 │ {} │ { title: null } │
│ 1 │ { title: null } │ { title: null } │
│ 2 │ { title: undefined } │ { title: null } │
│ 3 │ { title: "" } │ { title: null } │
│ 4 │ { title: "hello" } │ { title: "hello" } │
└───────┴──────────────────────┴────────────────────┘
4jandals
4jandalsOP2w ago
I had tried something similar on the zod side, but was getting a type error assigning the resolver. If I downgrade @hookform/resolvers from 5.0.1 to 4.1.3 it fixes the error, and now I can use the suggestion above. Thanks 👍
MEE6
MEE62w ago
Wohooo @4jandals, you just became a Waspeteer level 1!

Did you find this page helpful?