Edit Form

Data provider resources and routes are correctly implemented. Here is my edit component :
import { Nullable, Product, IProductFormData } from "@/interfaces";
import { ProductCreateForm } from "../../components";
import { useForm } from "@refinedev/react-hook-form";
import { FormProvider } from "react-hook-form";
import { HttpError, useOne } from "@refinedev/core";
import { zodResolver } from "@hookform/resolvers/zod";
import { productFormSchema } from "@/utils/zod/productFormValidation";
import { DevTool } from "@hookform/devtools";

export const ProductEdit = () => {
const methods = useForm<Product, HttpError, Nullable<IProductFormData>>({
// defaultValues: data?.data?.data[0] as Nullable<IProductFormData>,
refineCoreProps: {
redirect: false,
},
defaultValues: async () => {
//@ts-ignore
const response = await data_provider_typed.getOne({
resource: "products",
id: 146,
});
return response.data;
},

resolver: zodResolver(productFormSchema)
});

return (
<FormProvider {...methods}>
<DevTool control={methods.control} />
<Edit isLoading={isLoading} saveButtonProps={saveButtonProps}>
<TextFieldElement
name="name"
label={t("products.fields.name")}
fullWidth
autoFocus
/>
<TextFieldElement
name="description"
label={t("products.fields.description")}
multiline
rows={4}
fullWidth
/>

</Edit>
</FormProvider>
);
};
import { Nullable, Product, IProductFormData } from "@/interfaces";
import { ProductCreateForm } from "../../components";
import { useForm } from "@refinedev/react-hook-form";
import { FormProvider } from "react-hook-form";
import { HttpError, useOne } from "@refinedev/core";
import { zodResolver } from "@hookform/resolvers/zod";
import { productFormSchema } from "@/utils/zod/productFormValidation";
import { DevTool } from "@hookform/devtools";

export const ProductEdit = () => {
const methods = useForm<Product, HttpError, Nullable<IProductFormData>>({
// defaultValues: data?.data?.data[0] as Nullable<IProductFormData>,
refineCoreProps: {
redirect: false,
},
defaultValues: async () => {
//@ts-ignore
const response = await data_provider_typed.getOne({
resource: "products",
id: 146,
});
return response.data;
},

resolver: zodResolver(productFormSchema)
});

return (
<FormProvider {...methods}>
<DevTool control={methods.control} />
<Edit isLoading={isLoading} saveButtonProps={saveButtonProps}>
<TextFieldElement
name="name"
label={t("products.fields.name")}
fullWidth
autoFocus
/>
<TextFieldElement
name="description"
label={t("products.fields.description")}
multiline
rows={4}
fullWidth
/>

</Edit>
</FormProvider>
);
};
Form elements are not getting the default values in here
2 Replies
kapa.ai
kapa.ai4w ago
Hi @Mohit. 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 provided code and the knowledge sources, I can see that you're using the useForm hook from @refinedev/react-hook-form to create an edit form for a product. The issue you're facing is that the form elements are not getting the default values. Let's address this problem: 1. First, you're using defaultValues as an async function, which is correct for fetching data from an API. However, you're not using the useForm hook correctly in the context of refine. 2. In refine, when using useForm for editing, you should let the hook handle the data fetching for you. Here's how you can modify your code to make it work:
import { useForm } from "@refinedev/react-hook-form";
import { Edit } from "@refinedev/mui";

export const ProductEdit = () => {
const {
refineCore: { formLoading, queryResult },
saveButtonProps,
register,
control,
formState: { errors },
} = useForm<IProduct, HttpError, IProductFormData>({
refineCoreProps: {
resource: "products",
id: 146, // or use dynamic id
redirect: false,
},
resolver: zodResolver(productFormSchema)
});

const productsData = queryResult?.data?.data;

return (
<Edit isLoading={formLoading} saveButtonProps={saveButtonProps}>
<form>
<TextFieldElement
{...register("name")}
label={t("products.fields.name")}
fullWidth
autoFocus
/>
<TextFieldElement
{...register("description")}
label={t("products.fields.description")}
multiline
rows={4}
fullWidth
/>
</form>
</Edit>
);
};
import { useForm } from "@refinedev/react-hook-form";
import { Edit } from "@refinedev/mui";

export const ProductEdit = () => {
const {
refineCore: { formLoading, queryResult },
saveButtonProps,
register,
control,
formState: { errors },
} = useForm<IProduct, HttpError, IProductFormData>({
refineCoreProps: {
resource: "products",
id: 146, // or use dynamic id
redirect: false,
},
resolver: zodResolver(productFormSchema)
});

const productsData = queryResult?.data?.data;

return (
<Edit isLoading={formLoading} saveButtonProps={saveButtonProps}>
<form>
<TextFieldElement
{...register("name")}
label={t("products.fields.name")}
fullWidth
autoFocus
/>
<TextFieldElement
{...register("description")}
label={t("products.fields.description")}
multiline
rows={4}
fullWidth
/>
</form>
</Edit>
);
};
This approach lets refine handle the data fetching and form state management. The queryResult will contain the fetched data, and the form fields will automatically be populated with the default values. 3. If you need to use FormProvider and DevTool, you can still include them, but make sure to use the control from the useForm hook:
import { FormProvider } from "react-hook-form";
import { DevTool } from "@hookform/devtools";

// ... (rest of the imports)

export const ProductEdit = () => {
const {
refineCore: { formLoading, queryResult },
saveButtonProps,
register,
control,
formState: { errors },
} = useForm<IProduct, HttpError, IProductFormData>({
// ... (same as above)
});

return (
<FormProvider {...{ control, register, formState: { errors } }}>
<DevTool control={control} />
<Edit isLoading={formLoading} saveButtonProps={saveButtonProps}>
{/* ... (form fields as above) */}
</Edit>
</FormProvider>
);
};
import { FormProvider } from "react-hook-form";
import { DevTool } from "@hookform/devtools";

// ... (rest of the imports)

export const ProductEdit = () => {
const {
refineCore: { formLoading, queryResult },
saveButtonProps,
register,
control,
formState: { errors },
} = useForm<IProduct, HttpError, IProductFormData>({
// ... (same as above)
});

return (
<FormProvider {...{ control, register, formState: { errors } }}>
<DevTool control={control} />
<Edit isLoading={formLoading} saveButtonProps={saveButtonProps}>
{/* ... (form fields as above) */}
</Edit>
</FormProvider>
);
};
These changes should resolve the issue of form elements not getting the default values. The useForm hook from refine will handle fetching the data and populating the form fields automatically. For more detailed information on using useForm with refine, you can refer to the Refine React Hook Form documentation. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai4w ago
<@562507430341115905> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?