Form submission
When it's time to submit the form, it is handy to have a custom hook that handles all the logic behind submission. This can help keeping the component clean by abstracting the logic away, especially when calling multiple services or doing a lot when submitting the form
#
1. Create a custom hookThis should handle everything that needs to happen when subbmitting the form including calling mutation services or redirecting the user back to overview page etc
components/organization-units/details/hooks/useCompanyInfoSubmit.ts
export const useCompanyInfoSubmit = () => { const intl = useIntl(); const { addNotification } = useContext(NotificationsContext);
// Service mutation handlers const { updateOrganizationUnit, isUpdateOULoading } = useUpdateOrganizationUnit(); const { updateOrganizationUnitSettings, isUpdateOUSettingsLoading } = useUpdateOrganizationUnitSettings(); const { updateOrganizationUnitNotes, isUpdateOUNotesLoading } = useUpdateOrganizationUnitNotes();
// Other logic that we need to do when submitting the form const setCurrentEditingCardTab = useSetRecoilState(basicInformationTabCardBeingEdited);
// This is the submit handler that will be called when the form is submitted. const handleSubmit = useCallback( (basicInfoValues: IBasicInformationDetails) => { if (basicInfoValues.ID) { const promises = [ updateOrganizationUnit({ ID: basicInfoValues.ID, Name: basicInfoValues.Name, RegistrationNumber: basicInfoValues.RegistrationNumber, VatNumber: basicInfoValues.VatNumber, BankAccount: basicInfoValues.BankAccount, }), updateOrganizationUnitSettings({ ID: basicInfoValues.ID, AssortmentID: basicInfoValues.AssortmentID, }), updateOrganizationUnitNotes({ OrganizationUnitID: basicInfoValues.ID, Notes: basicInfoValues.Notes ?? '', }), ];
Promise.all(promises).then((responses) => { if (responses.every((response) => !isNil(response))) { setCurrentEditingCardTab(undefined); addNotification({ message: intl.formatMessage({ id: 'organizations.details.tabs.basic-info.company-info.success.message', }), showIcon: true, iconType: 'success', }); } }); } }, [ addNotification, intl, setCurrentEditingCardTab, updateOrganizationUnit, updateOrganizationUnitNotes, updateOrganizationUnitSettings, ], );
// State that keeps track of when the action is already in progress const isUpdateInProgress = useMemo( () => isUpdateOULoading || isUpdateOUSettingsLoading || isUpdateOUNotesLoading, [isUpdateOULoading, isUpdateOUNotesLoading, isUpdateOUSettingsLoading], );
return { handleSubmit, isUpdateInProgress };};
We usually return a loading state alongside the submit handler that the component can use to show a progress bar and disable the submit button when the there's already a create/update action in progress.
#
2. Use the custom hook in the form componentCall the submit handler from the custom hook in your form component.
components/organization-units/details/CompanyInfoCard.tsx
const CompanyInfoCard = () => { ...
const initialValues = useMemo<IBasicInformationDetails>( () => ({ ID: organizationUnitDetailsResponse?.ID, Name: organizationUnitDetailsResponse?.Name, RegistrationNumber: organizationUnitDetailsResponse?.RegistrationNumber, VatNumber: organizationUnitDetailsResponse?.VatNumber, BankAccount: organizationUnitDetailsResponse?.BankAccount, AssortmentID: organizationUnitSettingsResponse?.AssortmentID, AssortmentName: organizationUnitSettingsResponse?.AssortmentName, Notes: organizationUnitNotesResponse?.Notes, }), [ organizationUnitDetailsResponse?.BankAccount, organizationUnitDetailsResponse?.ID, organizationUnitDetailsResponse?.Name, organizationUnitDetailsResponse?.RegistrationNumber, organizationUnitDetailsResponse?.VatNumber, organizationUnitNotesResponse?.Notes, organizationUnitSettingsResponse?.AssortmentID, organizationUnitSettingsResponse?.AssortmentName, ], );
const validationSchema = useCompanyInfoValidationSchema();
const { handleSubmit, isUpdateInProgress } = useCompanyInfoSubmit();
return ( <RelativeBox> <ProgressBar position="top" loading={isUpdateInProgress} /> <Card inner> <Formik initialValues={initialValues} enableReinitialize validationSchema={validationSchema} onSubmit={(values, formikHelpers) => { handleSubmit(values); formikHelpers.setSubmitting(false); }} > {({ setFieldValue }) => ( <> <EditableCardHeader title={intl.formatMessage({ id: 'organizations.details.tabs.basic-info.company-info.title', })} editModeTitle={intl.formatMessage({ id: 'organizations.details.tabs.basic-info.company-info.edit-mode.title', })} tabCard={BasicInformationTabCard.CompanyInfo} isEditModeState={basicInformationTabCardBeingEdited} isActionsDisabled={isUpdateInProgress} isCurrentlyEditingTabCardSelector={isCurrentlyEditingBasicInformationTabCard( BasicInformationTabCard.CompanyInfo, )} /> ... </> )} </Formik> </Card> </RelativeBox> );};