useForm with Different Input/Submit Types Not Working as Expected
useForm with Different Input/Submit Types Not Working as Expected
Description
I'm using useForm<BookDto, HttpError, UpdateBookRequest>() in edit mode
and facing broken behavior when trying to use a different shape for the loaded data vs. the submitted data.
Types
// Fetched data from API (BookDto)
{
categories: { id: number; name: string }[];
}
// What my API expects on submit (UpdateBookRequest)
{
categoryIds: number[];
}
Expected
I want to use:
<Controller name="categoryIds" ... />
And prefill it from:
record.categories → categoryIds
Actual Behavior
- If I use
name="categoryIds",field.valueis alwaysundefinedeven thoughcategoriesexists in the record. - If I use
name="categories",field.valueis correct — but the form fails sincecategoriesdoesn't exist inUpdateBookRequest.
Code
const {
control,
saveButtonProps,
register,
formState: { errors },
} = useForm<BookDto, HttpError, UpdateBookRequest>({
});
<Controller
control={control}
name="categoryIds"
render={({ field }) => (
<BookCategoryTags {...field} />
)}
/>
Template Used
Using the official Material UI template from Refine: https://refine.dev/templates/material-ui-template
What’s the correct way to handle different types for input and submit?
It seems like the TData type is used everywhere, including defaultValues,
which makes it impossible to cleanly handle BookDto → UpdateBookRequest transformations.
Either I'm missing something, or the typing and form behavior are not production ready for real-world DTO mapping.
Please clarify or fix this behavior
I’ve spent hours trying to get this working and ran into silent failures and inconsistent behavior. Would appreciate a real-world solution that supports:
- Different types for fetch vs submit
- Clean default values mapping
- Proper form state hydration
Thank you.
I'm keen to address this useForm issue as it highlights a critical challenge in real-world DTO mapping that impacts developer experience and type safety. My extensive experience with TypeScript and form libraries like React Hook Form (which Refine's useForm builds upon) makes me well-suited to clarify and fix this behavior. I understand the complexities of managing different data shapes for fetching versus submission.