Задать вопрос
@Andrey1302
FullStack Developer (React.js | Node.js | Nest.js)

REACT-HOOK-FORM. Как синхронизировать defaultValues с данными, получаемыми из react-query запроса?

Использую 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 описанных выше кейса?
  • Вопрос задан
  • 27 просмотров
Подписаться 1 Средний Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы