exotic-emerald
exotic-emerald13mo ago

Reusability

Most of the refine repo examples which i have seen, contains 2 files for create and edit, which are almost similar to each other., which causes duplication of form fields their validations, is there any example which avoids this?? For example consider below code for creation of courier resource: how can i make edit using reusing the fields ??
14 Replies
kapa.ai
kapa.ai13mo ago
Hi @dreamer9067. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- In refine, the code for creating and editing a resource is indeed quite similar. However, you can avoid duplication by creating a reusable component for the form fields and their validations. This component can then be used in both the create and edit pages. Here's an example of how you can do this using the code you provided:
import {
Create,
DatePicker,
Form,
Input,
IResourceComponentsProps,
Switch,
useForm,
} from "@pankod/refine";
import dayjs from "dayjs";

// This is your reusable form component
const CampaignForm: React.FC<IResourceComponentsProps> = ({ formProps }) => (
<Form
{...formProps}
layout="vertical"
initialValues={{ isActive: false }}
>
<Form.Item
label="Name"
name="name"
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="Is Active"
name="isActive"
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label="Start Date"
name="startDate"
rules={[
{
required: true,
},
]}
getValueProps={(value) => dayjs(value)}
>
<DatePicker />
</Form.Item>
<Form.Item
label="End Date"
name="endDate"
rules={[
{
required: true,
},
]}
getValueProps={(value) => dayjs(value)}
>
<DatePicker />
</Form.Item>
</Form>
);

// This is your create page
export const CampaignsCreate: React.FC<IResourceComponentsProps> = () => {
const { formProps, saveButtonProps } = useForm();

return (
<Create saveButtonProps={saveButtonProps}>
<CampaignForm formProps={formProps} />
</Create>
);
};
// This is your edit page
export const CampaignsEdit: React.FC<IResourceComponentsProps> = () => {
const { formProps, saveButtonProps } = useForm();

return (
<Edit saveButtonProps={saveButtonProps}>
<CampaignForm formProps={formProps} />
</Edit>
);
};
import {
Create,
DatePicker,
Form,
Input,
IResourceComponentsProps,
Switch,
useForm,
} from "@pankod/refine";
import dayjs from "dayjs";

// This is your reusable form component
const CampaignForm: React.FC<IResourceComponentsProps> = ({ formProps }) => (
<Form
{...formProps}
layout="vertical"
initialValues={{ isActive: false }}
>
<Form.Item
label="Name"
name="name"
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="Is Active"
name="isActive"
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label="Start Date"
name="startDate"
rules={[
{
required: true,
},
]}
getValueProps={(value) => dayjs(value)}
>
<DatePicker />
</Form.Item>
<Form.Item
label="End Date"
name="endDate"
rules={[
{
required: true,
},
]}
getValueProps={(value) => dayjs(value)}
>
<DatePicker />
</Form.Item>
</Form>
);

// This is your create page
export const CampaignsCreate: React.FC<IResourceComponentsProps> = () => {
const { formProps, saveButtonProps } = useForm();

return (
<Create saveButtonProps={saveButtonProps}>
<CampaignForm formProps={formProps} />
</Create>
);
};
// This is your edit page
export const CampaignsEdit: React.FC<IResourceComponentsProps> = () => {
const { formProps, saveButtonProps } = useForm();

return (
<Edit saveButtonProps={saveButtonProps}>
<CampaignForm formProps={formProps} />
</Edit>
);
};
In this example, CampaignForm is a reusable component that contains the form fields and their validations. It is used in both the CampaignsCreate and CampaignsEdit components. For more information, you can refer to the refine documentation (https://refine.dev/docs) and blog (https://refine.dev/blog). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai13mo ago
<@560876002046377984> kapa.ai is still learning and improving, please let us how it did by reacting below
exotic-emerald
exotic-emerald13mo ago
@kapa.ai can u use stepForms instead of plainForms and where would the header and footer of stepForm will go? will it be in common campaignForm or duplicated in create and edit component both??
kapa.ai
kapa.ai13mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- Yes, you can use useStepsForm instead of plain forms in refine. The useStepsForm hook allows you to manage a form with multiple steps. It provides features such as which step is currently active, the ability to go to a specific step, and validation when changing steps. The header and footer of the useStepsForm would typically be defined in the component where you use the useStepsForm hook. However, if the header and footer are the same for both the create and edit forms, you can define them in the common CampaignForm to avoid duplication. Here's an example of how you can do this:
import { useStepsForm } from "@pankod/refine";

// This is your reusable form component
const CampaignForm: React.FC<IResourceComponentsProps> = ({ formProps }) => {
const stepsForm = useStepsForm({
refineCoreProps: {
action: "edit",
resource: "posts",
id: "1",
},
});

return (
<StepsForm formProps={formProps} stepsForm={stepsForm}>
{/* Your form fields go here */}
</StepsForm>
);
};

// This is your create page
export const CampaignsCreate: React.FC<IResourceComponentsProps> = () => {
const { formProps, saveButtonProps } = useForm();

return (
<Create saveButtonProps={saveButtonProps}>
<CampaignForm formProps={formProps} />
</Create>
);
};

// This is your edit page
export const CampaignsEdit: React.FC<IResourceComponentsProps> = () => {
const { formProps, saveButtonProps } = useForm();

return (
<Edit saveButtonProps={saveButtonProps}>
<CampaignForm formProps={formProps} />
</Edit>
);
};
import { useStepsForm } from "@pankod/refine";

// This is your reusable form component
const CampaignForm: React.FC<IResourceComponentsProps> = ({ formProps }) => {
const stepsForm = useStepsForm({
refineCoreProps: {
action: "edit",
resource: "posts",
id: "1",
},
});

return (
<StepsForm formProps={formProps} stepsForm={stepsForm}>
{/* Your form fields go here */}
</StepsForm>
);
};

// This is your create page
export const CampaignsCreate: React.FC<IResourceComponentsProps> = () => {
const { formProps, saveButtonProps } = useForm();

return (
<Create saveButtonProps={saveButtonProps}>
<CampaignForm formProps={formProps} />
</Create>
);
};

// This is your edit page
export const CampaignsEdit: React.FC<IResourceComponentsProps> = () => {
const { formProps, saveButtonProps } = useForm();

return (
<Edit saveButtonProps={saveButtonProps}>
<CampaignForm formProps={formProps} />
</Edit>
);
};
In this example, CampaignForm is a reusable component that contains the form fields and their validations. It is used in both the CampaignsCreate and CampaignsEdit components. For more information, you can refer to the useStepsForm documentation (https://refine.dev/docs/api-reference/antd/hooks/form/useStepsForm/). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai13mo ago
<@560876002046377984> kapa.ai is still learning and improving, please let us how it did by reacting below
exotic-emerald
exotic-emerald13mo ago
@kapa.ai why we need to pass refineCoreProps as { action: "edit", resource: "posts", id: "1", } in CampaignForm, will it not break create form??
kapa.ai
kapa.ai13mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- You're correct. The refineCoreProps object with action: "edit" and id: "1" should not be hardcoded in the CampaignForm component. This would indeed break the create form, as it would always be in "edit" mode and tied to the post with id: "1". Instead, you should pass these props from the parent component (CampaignsCreate or CampaignsEdit) to the CampaignForm component. This way, you can specify different action and id values for the create and edit forms. Here's how you can do this:
// This is your reusable form component
const CampaignForm: React.FC<IResourceComponentsProps> = ({ formProps, refineCoreProps }) => {
const stepsForm = useStepsForm({ refineCoreProps });

return (
<StepsForm formProps={formProps} stepsForm={stepsForm}>
{/* Your form fields go here */}
</StepsForm>
);
};

// This is your create page
export const CampaignsCreate: React.FC<IResourceComponentsProps> = () => {
const { formProps, saveButtonProps } = useForm();

return (
<Create saveButtonProps={saveButtonProps}>
<CampaignForm formProps={formProps} refineCoreProps={{ action: "create", resource: "posts" }} />
</Create>
);
};

// This is your edit page
export const CampaignsEdit: React.FC<IResourceComponentsProps> = () => {
const { formProps, saveButtonProps } = useForm();

return (
<Edit saveButtonProps={saveButtonProps}>
<CampaignForm formProps={formProps} refineCoreProps={{ action: "edit", resource: "posts", id: "1" }} />
</Edit>
);
};
// This is your reusable form component
const CampaignForm: React.FC<IResourceComponentsProps> = ({ formProps, refineCoreProps }) => {
const stepsForm = useStepsForm({ refineCoreProps });

return (
<StepsForm formProps={formProps} stepsForm={stepsForm}>
{/* Your form fields go here */}
</StepsForm>
);
};

// This is your create page
export const CampaignsCreate: React.FC<IResourceComponentsProps> = () => {
const { formProps, saveButtonProps } = useForm();

return (
<Create saveButtonProps={saveButtonProps}>
<CampaignForm formProps={formProps} refineCoreProps={{ action: "create", resource: "posts" }} />
</Create>
);
};

// This is your edit page
export const CampaignsEdit: React.FC<IResourceComponentsProps> = () => {
const { formProps, saveButtonProps } = useForm();

return (
<Edit saveButtonProps={saveButtonProps}>
<CampaignForm formProps={formProps} refineCoreProps={{ action: "edit", resource: "posts", id: "1" }} />
</Edit>
);
};
In this example, refineCoreProps is passed as a prop to CampaignForm from CampaignsCreate and CampaignsEdit. The action and id values are specified in these parent components, allowing you to use different values for the create and edit forms. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai13mo ago
<@560876002046377984> kapa.ai is still learning and improving, please let us how it did by reacting below
exotic-emerald
exotic-emerald13mo ago
@kapa.ai getting form as undefined
kapa.ai
kapa.ai13mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- If you're getting form as undefined, it's likely that you're trying to access it before it's been defined. This could be due to the asynchronous nature of hooks in React. In the context of refine, the useForm or useStepsForm hooks return an object that includes formProps. You should use these formProps to pass the form instance to your Form component. Here's an example:
import { useForm } from "@pankod/refine";

export const MyComponent: React.FC = () => {
const { formProps } = useForm();

return (
<Form {...formProps}>
{/* Your form fields go here */}
</Form>
);
};
import { useForm } from "@pankod/refine";

export const MyComponent: React.FC = () => {
const { formProps } = useForm();

return (
<Form {...formProps}>
{/* Your form fields go here */}
</Form>
);
};
In this example, formProps is destructured from the object returned by useForm, and then passed to the Form component. If you're still having issues, please ensure that you're using the hooks correctly and that your component is within a refine context. For more information, you can refer to the refine documentation (https://refine.dev/docs). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai13mo ago
<@560876002046377984> kapa.ai is still learning and improving, please let us how it did by reacting below
exotic-emerald
exotic-emerald13mo ago
@kapa.ai for this code: // This is your reusable form component const CampaignForm: React.FC<IResourceComponentsProps> = ({ formProps, refineCoreProps }) => { const stepsForm = useStepsForm({ refineCoreProps }); return ( <StepsForm formProps={formProps} stepsForm={stepsForm}> {/* Your form fields go here */} </StepsForm> ); }; // This is your create page export const CampaignsCreate: React.FC<IResourceComponentsProps> = () => { const { formProps, saveButtonProps } = useForm(); return ( <Create saveButtonProps={saveButtonProps}> <CampaignForm formProps={formProps} refineCoreProps={{ action: "create", resource: "posts" }} /> </Create> ); }; // This is your edit page export const CampaignsEdit: React.FC<IResourceComponentsProps> = () => { const { formProps, saveButtonProps } = useForm(); return ( <Edit saveButtonProps={saveButtonProps}> <CampaignForm formProps={formProps} refineCoreProps={{ action: "edit", resource: "posts", id: "1" }} /> </Edit> ); }; i'm getting form as undefined in CampaignForm??
kapa.ai
kapa.ai13mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- The issue might be due to the misuse of the useStepsForm hook. The useStepsForm hook is used to manage a form with multiple steps. It should be used in the parent component (Create or Edit) instead of the reusable form component. Here's how you can modify your code:
// This is your reusable form component
const CampaignForm: React.FC<IResourceComponentsProps> = ({ formProps }) => {
return (
<Form {...formProps}>
{/* Your form fields go here */}
</Form>
);
};

// This is your create page
export const CampaignsCreate: React.FC<IResourceComponentsProps> = () => {
const { formProps, saveButtonProps, stepsForm } = useStepsForm({ action: "create", resource: "posts" });

return (
<Create saveButtonProps={saveButtonProps}>
<StepsForm formProps={formProps} stepsForm={stepsForm}>
<CampaignForm formProps={formProps} />
</StepsForm>
</Create>
);
};

// This is your edit page
export const CampaignsEdit: React.FC<IResourceComponentsProps> = () => {
const { formProps, saveButtonProps, stepsForm } = useStepsForm({ action: "edit", resource: "posts", id: "1" });

return (
<Edit saveButtonProps={saveButtonProps}>
<StepsForm formProps={formProps} stepsForm={stepsForm}>
<CampaignForm formProps={formProps} />
</StepsForm>
</Edit>
);
};
// This is your reusable form component
const CampaignForm: React.FC<IResourceComponentsProps> = ({ formProps }) => {
return (
<Form {...formProps}>
{/* Your form fields go here */}
</Form>
);
};

// This is your create page
export const CampaignsCreate: React.FC<IResourceComponentsProps> = () => {
const { formProps, saveButtonProps, stepsForm } = useStepsForm({ action: "create", resource: "posts" });

return (
<Create saveButtonProps={saveButtonProps}>
<StepsForm formProps={formProps} stepsForm={stepsForm}>
<CampaignForm formProps={formProps} />
</StepsForm>
</Create>
);
};

// This is your edit page
export const CampaignsEdit: React.FC<IResourceComponentsProps> = () => {
const { formProps, saveButtonProps, stepsForm } = useStepsForm({ action: "edit", resource: "posts", id: "1" });

return (
<Edit saveButtonProps={saveButtonProps}>
<StepsForm formProps={formProps} stepsForm={stepsForm}>
<CampaignForm formProps={formProps} />
</StepsForm>
</Edit>
);
};
In this example, useStepsForm is used in the CampaignsCreate and CampaignsEdit components. The formProps from useStepsForm are then passed to the CampaignForm component. For more information, you can refer to the useStepsForm documentation (https://refine.dev/docs/api-reference/antd/hooks/form/useStepsForm/). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai13mo ago
<@560876002046377984> kapa.ai is still learning and improving, please let us how it did by reacting below