Использую react-hook-form вместе с react-query. В родителе вызываю query, из полученных данных формирую defaultValues и прокидываю в компонент формы.
Agreement.tsx
export const Agreement = ({ clientId }: AgreementProps) => {
const { data, isLoading, isFetching, error } = useGetServiceAgreement(
{
clientId,
},
{
meta: {
isolatedErrorHandling: true,
},
},
);
if (isLoading) {
return (
<div className="space-y-6">
<Skeleton className="h-9 w-full" />
<Skeleton className="h-9 w-full" />
</div>
);
}
if (error) {
return <ErrorAlert error={error} errorMapper={ErrorMapper} />;
}
if (!data) return null;
const { description = '', clientCommissionPercent } = data;
const defaultValues = {
description,
clientCommissionPercent,
};
return (
<div className="relative p-4">
{isFetching && <LoadingOverlay />}
<AgreementForm defaultValues={defaultValues} clientId={clientId} />
</div>
);
};
AgreementForm.tsx
export const AgreementForm = ({
defaultValues,
clientId,
}: AgreementFormProps) => {
const { mutateAsync: updateAgreement } = useUpdateClientServiceAgreement();
const methods = useForm<ClientAgreementFormData>({
resolver: yupResolver(ClientAgreementSchema),
defaultValues: defaultValues ?? ClientAgreementSchema.getDefault(),
});
const { formState, reset, handleSubmit } = methods;
const { isSubmitting, isSubmitSuccessful } = formState;
useEffect(() => {
if (!defaultValues) return;
reset(defaultValues, FORM_RESET_CONFIG);
}, [reset, defaultValues, isSubmitSuccessful]);
const onSubmit = async (data: ClientAgreementFormData) => {
await updateAgreement({
clientId,
updateClientServiceAgreementRequest: data,
});
toast.success('Agreement updated successfully.');
};
return (
<Form {...methods}>
<form className="space-y-6">
<AgreementFields />
<div>
<Button onClick={handleSubmit(onSubmit)} isLoading={isSubmitting}>
Save
</Button>
</div>
</form>
</Form>
);
};
Не понимаю как синхронизировать значения формы с дефолтными значениями если они обновились.
1. react-query перезапрашивает данные на window focus (refetchOnWindowFocus: true). В этом случае кажется логичным обновить новыми значениями поля, которые не были тронуты пользователем. Для этого делаю:
useEffect(() => {
if (!defaultValues) return;
reset(defaultValues, FORM_RESET_CONFIG);
}, [reset, defaultValues, isSubmitSuccessful]);
где
export const FORM_RESET_CONFIG = {
keepDirtyValues: true,
keepErrors: true,
keepTouched: true,
keepIsSubmitted: true,
keepSubmitCount: true,
keepIsValid: true,
};
2. Когда onSubmit успешно завершился нужно сбросить ВСЕ поля формы. В этом случае нужно сделать reset(valuesFromPostResponse) без FORM_RESET_CONFIG.
Вопросы:
1. Нужно ли действительно синхронизировать значения формы с дефолтными значениями если дефолтные значения изменились?
2. Как реализовать для одной формы одновременно 2 описанных выше кейса?