useStepForm from react-form-hooks doesn't work as expected

When using useStepsForm<BaseRecord, HttpError, MyFields> and going to the next step, the gotoStep fails, as it fails the validation for the fields in the non active steps (like in the next step). For example lets say I have this:
const form = useStepsForm<BaseRecord, HttpError, CreatePropertyFields>({
resolver: zodResolver(createFormScheme),
});


const {
refineCore: {onFinish, formLoading},
register,
handleSubmit,
formState: {errors},
steps: {currentStep, gotoStep},
} = form;


const t = useTranslate()

const renderFormByStep = (step: number) => {


switch(step) {
case 0:
return (
<FormField
control={form.control}
name="title"
render={({field}) => (
<FormItem>
<FormLabel withAsterisk>Title</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage/>
</FormItem>)}
/>
);
case 1:
return (
<FormField
control={form.control}
name="test"
render={({field}) => (
<FormItem>
<FormLabel withAsterisk>Test</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage/>
</FormItem>)}
/>
);
}
};
const form = useStepsForm<BaseRecord, HttpError, CreatePropertyFields>({
resolver: zodResolver(createFormScheme),
});


const {
refineCore: {onFinish, formLoading},
register,
handleSubmit,
formState: {errors},
steps: {currentStep, gotoStep},
} = form;


const t = useTranslate()

const renderFormByStep = (step: number) => {


switch(step) {
case 0:
return (
<FormField
control={form.control}
name="title"
render={({field}) => (
<FormItem>
<FormLabel withAsterisk>Title</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage/>
</FormItem>)}
/>
);
case 1:
return (
<FormField
control={form.control}
name="test"
render={({field}) => (
<FormItem>
<FormLabel withAsterisk>Test</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage/>
</FormItem>)}
/>
);
}
};
17 Replies
kapa.ai
kapa.ai5w ago
Hi @BlackBearFTW. 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 information provided in the knowledge sources, it appears that you're encountering an issue with the useStepsForm hook from @refinedev/react-hook-form. This issue is related to the validation behavior when navigating between steps. Let me explain the problem and provide a solution. The issue you're experiencing is due to the default behavior of useStepsForm, where it validates all fields, including those in non-active steps, when moving to the next step. This can cause the gotoStep function to fail if there are required fields in future steps that haven't been filled out yet. To resolve this issue, you can use the isBackValidate option when initializing useStepsForm. By default, this option is set to true, which causes the validation to occur for all steps. Setting it to false will prevent validation when moving backwards through the steps. Here's how you can modify your code to fix this issue:
const form = useStepsForm<BaseRecord, HttpError, CreatePropertyFields>({
resolver: zodResolver(createFormScheme),
isBackValidate: false, // Add this line
});
const form = useStepsForm<BaseRecord, HttpError, CreatePropertyFields>({
resolver: zodResolver(createFormScheme),
isBackValidate: false, // Add this line
});
By adding isBackValidate: false, you're telling the hook to not validate fields when moving backwards through the steps. This should allow you to navigate between steps without encountering validation errors for fields in non-active steps. This solution is based on the information from the following issue: Github Issue: [BUG] Antd useStepsForm uses isBackValidate=true Additionally, if you want more control over the validation process, you can implement a custom validation function. Here's an example of how you might do this:
const {
// ... other destructured properties
steps: { currentStep, gotoStep },
} = useStepsForm<IPost, HttpError, FormValues>({
initialValues: {
title: "",
status: "",
slug: "",
content: "",
},
validate: (values) => {
if (currentStep === 0) {
return {
title: values.title ? null : "Title is required",
slug: values.slug ? null : "Slug is required",
};
}

if (currentStep === 1) {
return {
status: values.status ? null : "Status is required",
};
}

return {};
},
});
const {
// ... other destructured properties
steps: { currentStep, gotoStep },
} = useStepsForm<IPost, HttpError, FormValues>({
initialValues: {
title: "",
status: "",
slug: "",
content: "",
},
validate: (values) => {
if (currentStep === 0) {
return {
title: values.title ? null : "Title is required",
slug: values.slug ? null : "Slug is required",
};
}

if (currentStep === 1) {
return {
status: values.status ? null : "Status is required",
};
}

return {};
},
});
This example is adapted from the Mantine useStepsForm documentation. By implementing a custom validation function, you can control which fields are validated at each step, ensuring that only the relevant fields for the current step are checked. Remember to adjust the validation logic according to your specific form structure and requirements. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5w ago
<@490961337896402944> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
sensitive-blue
sensitive-blueOP5w ago
const form = useStepsForm<BaseRecord, HttpError, CreatePropertyFields>({
resolver: zodResolver(createFormScheme),
stepsProps: {
isBackValidate: false
},
defaultValues: {
title: "",
description: "",
roomCount: 1,
constructionType: "",
areaInSquareMeter: 0,
plotAreaInSquareMeter: 0,
newConstruction: false,
address: {
postalCode: "",
houseNumber: 0,
houseNumberAddition: undefined,
streetName: "",
city: "",
},
offerSettings: {
minimalOfferAmount: 0,
targetedAmount: 0,
stepPerOffer: 0,
realtorFee: 0,
allowOffersWithBuildingInspectionClause: false,
},
}
});


const {
refineCore: {onFinish, formLoading},
register,
handleSubmit,
formState: {errors},
steps: {currentStep, gotoStep},
} = form;
const form = useStepsForm<BaseRecord, HttpError, CreatePropertyFields>({
resolver: zodResolver(createFormScheme),
stepsProps: {
isBackValidate: false
},
defaultValues: {
title: "",
description: "",
roomCount: 1,
constructionType: "",
areaInSquareMeter: 0,
plotAreaInSquareMeter: 0,
newConstruction: false,
address: {
postalCode: "",
houseNumber: 0,
houseNumberAddition: undefined,
streetName: "",
city: "",
},
offerSettings: {
minimalOfferAmount: 0,
targetedAmount: 0,
stepPerOffer: 0,
realtorFee: 0,
allowOffersWithBuildingInspectionClause: false,
},
}
});


const {
refineCore: {onFinish, formLoading},
register,
handleSubmit,
formState: {errors},
steps: {currentStep, gotoStep},
} = form;
const createFormScheme = z.object({
title: z.string().min(1, "Title is required"),
description: z.string().min(1, "Description is required"),
roomCount: z.coerce.number().min(1).default(1),
constructionType: z.string().min(1, "Construction type is required"),
areaInSquareMeter: z.coerce.number().min(0.5).default(0),
plotAreaInSquareMeter: z.coerce.number().min(0.5).default(0),
newConstruction: z.boolean().default(false),
address: z.object({
postalCode: z.string().regex(/^[0-9]{4} [A-Za-z]{2}$/, "Invalid format (e.g., 1234 AB)"),
houseNumber: z.coerce.number().min(1).default(0),
houseNumberAddition: z.string().optional(),
streetName: z.string().min(1, "Street name is required"),
city: z.string().min(1, "City is required"),
}),
offerSettings: z.object({
minimalOfferAmount: z.coerce.number().min(0).default(0),
targetedAmount: z.coerce.number().min(0).default(0),
stepPerOffer: z.coerce.number().min(0).default(0),
realtorFee: z.coerce.number().min(0).default(0),
allowOffersWithBuildingInspectionClause: z.boolean().default(false),

}),
test: z.string().min(1, "Title is required"),
})

export type CreatePropertyFields = z.infer<typeof createFormScheme>;
const createFormScheme = z.object({
title: z.string().min(1, "Title is required"),
description: z.string().min(1, "Description is required"),
roomCount: z.coerce.number().min(1).default(1),
constructionType: z.string().min(1, "Construction type is required"),
areaInSquareMeter: z.coerce.number().min(0.5).default(0),
plotAreaInSquareMeter: z.coerce.number().min(0.5).default(0),
newConstruction: z.boolean().default(false),
address: z.object({
postalCode: z.string().regex(/^[0-9]{4} [A-Za-z]{2}$/, "Invalid format (e.g., 1234 AB)"),
houseNumber: z.coerce.number().min(1).default(0),
houseNumberAddition: z.string().optional(),
streetName: z.string().min(1, "Street name is required"),
city: z.string().min(1, "City is required"),
}),
offerSettings: z.object({
minimalOfferAmount: z.coerce.number().min(0).default(0),
targetedAmount: z.coerce.number().min(0).default(0),
stepPerOffer: z.coerce.number().min(0).default(0),
realtorFee: z.coerce.number().min(0).default(0),
allowOffersWithBuildingInspectionClause: z.boolean().default(false),

}),
test: z.string().min(1, "Title is required"),
})

export type CreatePropertyFields = z.infer<typeof createFormScheme>;
If I only have some fields on the first page, I cannot go to the next page, as it tried to validate fields that haven't been shown yet. @kapa.ai @Batu
kapa.ai
kapa.ai5w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- You're right, and I apologize for not addressing this specific issue in my previous answer. The problem you're describing is indeed a known issue with the useStepsForm hook. Let me provide a more accurate and relevant solution based on the information in our knowledge sources. The issue you're facing is related to the default validation behavior of useStepsForm. By default, it tries to validate all fields, including those that haven't been rendered yet, which prevents you from moving to the next step. To solve this problem, you need to implement a custom validation function that only validates the fields present in the current step. Here's how you can modify your useStepsForm implementation:
const {
saveButtonProps,
getInputProps,
values,
steps: { currentStep, gotoStep },
} = useStepsForm<IPost, HttpError, FormValues>({
initialValues: {
title: "",
status: "",
slug: "",
content: "",
},
validate: (values) => {
if (currentStep === 0) {
return {
title: values.title ? null : "Title is required",
slug: values.slug ? null : "Slug is required",
};
}

if (currentStep === 1) {
return {
status: values.status ? null : "Status is required",
};
}

return {};
},
});
const {
saveButtonProps,
getInputProps,
values,
steps: { currentStep, gotoStep },
} = useStepsForm<IPost, HttpError, FormValues>({
initialValues: {
title: "",
status: "",
slug: "",
content: "",
},
validate: (values) => {
if (currentStep === 0) {
return {
title: values.title ? null : "Title is required",
slug: values.slug ? null : "Slug is required",
};
}

if (currentStep === 1) {
return {
status: values.status ? null : "Status is required",
};
}

return {};
},
});
This example is adapted from the Mantine useStepsForm documentation. By implementing this custom validation function, you ensure that: 1. Only the fields present in the current step are validated. 2. You can move to the next step without validating fields that haven't been rendered yet. 3. Each step has its own specific validation rules. Remember to adjust the validation logic according to your specific form structure and the fields present in each step of your form. This approach should allow you to navigate to the next page even when you only have some fields on the first page, as it will only validate the fields that are actually present in the current step. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5w ago
<@490961337896402944> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
sensitive-blue
sensitive-blueOP4w ago
..... any mod please why does this work this way @kapa.ai how can I use a multi step form with zod validation
kapa.ai
kapa.ai4w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- To use a multi-step form with Zod validation in refine, you can combine the useStepsForm hook with Zod schema validation. Here's how you can implement this: 1. First, import the necessary dependencies:
import { useStepsForm } from "@refinedev/react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import * as z from "zod";
import { useStepsForm } from "@refinedev/react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import * as z from "zod";
2. Define your Zod schema for each step:
const stepOneSchema = z.object({
title: z.string().min(1, "Title is required"),
slug: z.string().min(1, "Slug is required"),
});

const stepTwoSchema = z.object({
status: z.enum(["published", "draft", "rejected"]),
});

const stepThreeSchema = z.object({
content: z.string().min(1, "Content is required"),
});

const formSchema = z.object({
...stepOneSchema.shape,
...stepTwoSchema.shape,
...stepThreeSchema.shape,
});

type FormValues = z.infer<typeof formSchema>;
const stepOneSchema = z.object({
title: z.string().min(1, "Title is required"),
slug: z.string().min(1, "Slug is required"),
});

const stepTwoSchema = z.object({
status: z.enum(["published", "draft", "rejected"]),
});

const stepThreeSchema = z.object({
content: z.string().min(1, "Content is required"),
});

const formSchema = z.object({
...stepOneSchema.shape,
...stepTwoSchema.shape,
...stepThreeSchema.shape,
});

type FormValues = z.infer<typeof formSchema>;
3. Use the useStepsForm hook with Zod validation:
const {
saveButtonProps,
getInputProps,
values,
steps: { currentStep, gotoStep },
} = useStepsForm<IPost, HttpError, FormValues>({
resolver: zodResolver(formSchema),
validate: (values) => {
if (currentStep === 0) {
return zodResolver(stepOneSchema)(values);
}
if (currentStep === 1) {
return zodResolver(stepTwoSchema)(values);
}
if (currentStep === 2) {
return zodResolver(stepThreeSchema)(values);
}
return {};
},
initialValues: {
title: "",
status: "draft",
slug: "",
content: "",
},
});
const {
saveButtonProps,
getInputProps,
values,
steps: { currentStep, gotoStep },
} = useStepsForm<IPost, HttpError, FormValues>({
resolver: zodResolver(formSchema),
validate: (values) => {
if (currentStep === 0) {
return zodResolver(stepOneSchema)(values);
}
if (currentStep === 1) {
return zodResolver(stepTwoSchema)(values);
}
if (currentStep === 2) {
return zodResolver(stepThreeSchema)(values);
}
return {};
},
initialValues: {
title: "",
status: "draft",
slug: "",
content: "",
},
});
4. Render your form steps:
return (
<Create
footerButtons={
<Group position="right" mt="xl">
{currentStep > 0 && (
<Button variant="default" onClick={() => gotoStep(currentStep - 1)}>
Back
</Button>
)}
{currentStep < 2 && (
<Button onClick={() => gotoStep(currentStep + 1)}>Next step</Button>
)}
{currentStep === 2 && <SaveButton {...saveButtonProps} />}
</Group>
}
>
<Stepper active={currentStep} onStepClick={gotoStep} breakpoint="sm">
<Stepper.Step label="First Step" description="Title and Slug">
<TextInput
mt="md"
label="Title"
{...getInputProps("title")}
/>
<TextInput
mt="md"
label="Slug"
{...getInputProps("slug")}
/>
</Stepper.Step>
<Stepper.Step label="Second Step" description="Status">
<Select
mt="md"
label="Status"
{...getInputProps("status")}
data={[
{ label: "Published", value: "published" },
{ label: "Draft", value: "draft" },
{ label: "Rejected", value: "rejected" },
]}
/>
</Stepper.Step>
<Stepper.Step label="Final Step" description="Content">
<Textarea
label="Content"
{...getInputProps("content")}
/>
</Stepper.Step>
</Stepper>
</Create>
);
return (
<Create
footerButtons={
<Group position="right" mt="xl">
{currentStep > 0 && (
<Button variant="default" onClick={() => gotoStep(currentStep - 1)}>
Back
</Button>
)}
{currentStep < 2 && (
<Button onClick={() => gotoStep(currentStep + 1)}>Next step</Button>
)}
{currentStep === 2 && <SaveButton {...saveButtonProps} />}
</Group>
}
>
<Stepper active={currentStep} onStepClick={gotoStep} breakpoint="sm">
<Stepper.Step label="First Step" description="Title and Slug">
<TextInput
mt="md"
label="Title"
{...getInputProps("title")}
/>
<TextInput
mt="md"
label="Slug"
{...getInputProps("slug")}
/>
</Stepper.Step>
<Stepper.Step label="Second Step" description="Status">
<Select
mt="md"
label="Status"
{...getInputProps("status")}
data={[
{ label: "Published", value: "published" },
{ label: "Draft", value: "draft" },
{ label: "Rejected", value: "rejected" },
]}
/>
</Stepper.Step>
<Stepper.Step label="Final Step" description="Content">
<Textarea
label="Content"
{...getInputProps("content")}
/>
</Stepper.Step>
</Stepper>
</Create>
);
This implementation combines the useStepsForm hook with Zod schema validation. The validate function in useStepsForm uses the appropriate Zod schema for each step, ensuring that only the fields in the current step are validated when moving between steps. This approach is based on the usage examples from the Mantine useStepsForm documentation, adapted to include Zod validation. Remember to adjust the schemas and form fields according to your specific requirements. This example should provide you with a solid foundation for creating a multi-step form with Zod validation in refine. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai4w ago
<@490961337896402944> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
sensitive-blue
sensitive-blueOP4w ago
@kapa.ai validate function doesn't exist on useStepForm
kapa.ai
kapa.ai4w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I apologize for the confusion in my previous response. You are correct that the validate function is not a direct property of useStepsForm. Let me provide you with the correct information based on the refine documentation. The useStepsForm hook in refine doesn't have a validate property directly. Instead, you can use the resolver option to handle validation, including Zod validation. Here's how you can correctly implement validation with useStepsForm:
import { useStepsForm } from "@refinedev/react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import * as z from "zod";

// Define your Zod schema
const formSchema = z.object({
title: z.string().min(1, "Title is required"),
slug: z.string().min(1, "Slug is required"),
status: z.enum(["published", "draft", "rejected"]),
content: z.string().min(1, "Content is required"),
});

type FormValues = z.infer<typeof formSchema>;

const {
saveButtonProps,
getInputProps,
values,
steps: { currentStep, gotoStep },
} = useStepsForm<IPost, HttpError, FormValues>({
resolver: zodResolver(formSchema),
initialValues: {
title: "",
status: "draft",
slug: "",
content: "",
},
});
import { useStepsForm } from "@refinedev/react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import * as z from "zod";

// Define your Zod schema
const formSchema = z.object({
title: z.string().min(1, "Title is required"),
slug: z.string().min(1, "Slug is required"),
status: z.enum(["published", "draft", "rejected"]),
content: z.string().min(1, "Content is required"),
});

type FormValues = z.infer<typeof formSchema>;

const {
saveButtonProps,
getInputProps,
values,
steps: { currentStep, gotoStep },
} = useStepsForm<IPost, HttpError, FormValues>({
resolver: zodResolver(formSchema),
initialValues: {
title: "",
status: "draft",
slug: "",
content: "",
},
});
In this approach, you use the resolver option with zodResolver to handle the validation for all fields. However, this will validate all fields at once, which might not be ideal for a multi-step form. To validate only the fields in the current step, you can create separate schemas for each step and use them in your component logic. Here's an example of how you might structure this:
const stepOneSchema = z.object({
title: z.string().min(1, "Title is required"),
slug: z.string().min(1, "Slug is required"),
});

const stepTwoSchema = z.object({
status: z.enum(["published", "draft", "rejected"]),
});
const stepThreeSchema = z.object({
content: z.string().min(1, "Content is required"),
});

const formSchema = z.object({
...stepOneSchema.shape,
...stepTwoSchema.shape,
...stepThreeSchema.shape,
});

// In your component
const form = useStepsForm<IPost, HttpError, FormValues>({
resolver: zodResolver(formSchema),
// ... other options
});

// When moving to the next step
const handleNextStep = async () => {
let isValid = false;
if (currentStep === 0) {
isValid = await form.trigger(Object.keys(stepOneSchema.shape));
} else if (currentStep === 1) {
isValid = await form.trigger(Object.keys(stepTwoSchema.shape));
}
// ... and so on

if (isValid) {
form.steps.gotoStep(currentStep + 1);
}
};
const stepOneSchema = z.object({
title: z.string().min(1, "Title is required"),
slug: z.string().min(1, "Slug is required"),
});

const stepTwoSchema = z.object({
status: z.enum(["published", "draft", "rejected"]),
});
const stepThreeSchema = z.object({
content: z.string().min(1, "Content is required"),
});

const formSchema = z.object({
...stepOneSchema.shape,
...stepTwoSchema.shape,
...stepThreeSchema.shape,
});

// In your component
const form = useStepsForm<IPost, HttpError, FormValues>({
resolver: zodResolver(formSchema),
// ... other options
});

// When moving to the next step
const handleNextStep = async () => {
let isValid = false;
if (currentStep === 0) {
isValid = await form.trigger(Object.keys(stepOneSchema.shape));
} else if (currentStep === 1) {
isValid = await form.trigger(Object.keys(stepTwoSchema.shape));
}
// ... and so on

if (isValid) {
form.steps.gotoStep(currentStep + 1);
}
};
This approach uses the trigger method from react-hook-form (which is available through useStepsForm) to validate only the fields in the current step before moving to the next step. I apologize again for the earlier confusion. The refine documentation doesn't provide a direct example of step-by-step validation with Zod for useStepsForm, so this solution is based on combining information from the Mantine useStepsForm documentation and general react-hook-form practices. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai4w ago
<@490961337896402944> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
sensitive-blue
sensitive-blueOP4w ago
@kapa.ai how to validate useForm
kapa.ai
kapa.ai4w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- To validate a form using useForm in refine, you can use Zod for schema validation in combination with the zodResolver from @hookform/resolvers/zod. Here's how you can implement this: 1. First, import the necessary dependencies:
import { useForm } from "@refinedev/react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import * as zod from "zod";
import { useForm } from "@refinedev/react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import * as zod from "zod";
2. Define your Zod schema:
const PostSchema = zod.object({
title: zod.string().min(1, { message: "Title cannot be empty" }),
subtitle: zod.string().max(65, { message: "Keep subtitle shorter" }),
content: zod
.string()
.min(20, { message: "Content should have enough information" })
.max(1000, {
message: "Content has reached maximum limit of 1000 characters",
}),
});

type TPost = zod.infer<typeof PostSchema>;
const PostSchema = zod.object({
title: zod.string().min(1, { message: "Title cannot be empty" }),
subtitle: zod.string().max(65, { message: "Keep subtitle shorter" }),
content: zod
.string()
.min(20, { message: "Content should have enough information" })
.max(1000, {
message: "Content has reached maximum limit of 1000 characters",
}),
});

type TPost = zod.infer<typeof PostSchema>;
3. Use the useForm hook with Zod validation:
const formInstance = useForm<TPost>({
resolver: zodResolver(PostSchema),
mode: "onChange",
defaultValues: {
title: "",
subtitle: "",
content: "",
},
criteriaMode: "all",
shouldFocusError: true,
});
const formInstance = useForm<TPost>({
resolver: zodResolver(PostSchema),
mode: "onChange",
defaultValues: {
title: "",
subtitle: "",
content: "",
},
criteriaMode: "all",
shouldFocusError: true,
});
4. Use the form instance in your component:
const {
register,
handleSubmit,
formState: { errors },
} = formInstance;

return (
<form onSubmit={handleSubmit((data) => console.log(data))}>
<input {...register("title")} placeholder="Title" />
{errors.title && <span>{errors.title.message}</span>}

<input {...register("subtitle")} placeholder="Subtitle" />
{errors.subtitle && <span>{errors.subtitle.message}</span>}

<textarea {...register("content")} placeholder="Content" />
{errors.content && <span>{errors.content.message}</span>}

<button type="submit">Submit</button>
</form>
);
const {
register,
handleSubmit,
formState: { errors },
} = formInstance;

return (
<form onSubmit={handleSubmit((data) => console.log(data))}>
<input {...register("title")} placeholder="Title" />
{errors.title && <span>{errors.title.message}</span>}

<input {...register("subtitle")} placeholder="Subtitle" />
{errors.subtitle && <span>{errors.subtitle.message}</span>}

<textarea {...register("content")} placeholder="Content" />
{errors.content && <span>{errors.content.message}</span>}

<button type="submit">Submit</button>
</form>
);
This implementation uses Zod to define the schema and validate the form fields. The zodResolver is used to integrate Zod with react-hook-form, which is what useForm in refine is based on. The mode: "onChange" option makes the form validate on each change event, but you can adjust this according to your needs. This approach is based on the information from the Form Schema Validation with Zod and React Hook Form blog post on the refine website. Remember to adjust the schema and form fields according to your specific requirements. This example should provide you with a solid foundation for form validation using useForm with Zod in refine. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai4w ago
<@490961337896402944> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
foreign-sapphire
foreign-sapphire4w ago
Hello @BlackBearFTW, it seems there is a bug on useStepsform. Can you open github issue with reproducible example, please? We can track better the task on Github
sensitive-blue
sensitive-blueOP4w ago
Just take one of the website examples: https://refine.dev/docs/packages/react-hook-form/use-steps-form/, then add zod resolver to it
sensitive-blue
sensitive-blueOP4w ago
GitHub
[BUG] UseStepForm from headless not working with zod · Issue #6660 ...
Describe the bug Hi, I was trying to use the use-step -form from @refinedev/react-hook-form, however this doesn't properly work with zod validation. When you add validation, it will fail the va...

Did you find this page helpful?