React Formik Reset Country Field

  Kiến thức lập trình

the problem with my React components is that visually the country name does not reset when clicking on the “cancel” button.

import { useState, useRef } from 'react';
import { Form, Formik } from 'formik';
import { useTranslation } from 'react-i18next';
import { Button } from '@monorepo/kit-ui';
import { format, formatISO, parse } from 'date-fns';
import { IUpdateProfileForm } from '../../types';
import {
  useUpdateProfileFormSubmit,
  useUpdateProfileFormValidation,
} from '../../hooks';
import LastnameField from '../molecules/LastnameField';
import FirstnameField from '../molecules/FirstnameField';
import BirthdateField from '../molecules/BirthdateField';
import CountryField from '../molecules/CountryField';
import PhoneField from '../molecules/PhoneField';
import EmailField from '../molecules/EmailField';
import IsSubscribeNewsletterField from '../molecules/IsSubscribeNewsletterField';
import { useGetCurrentUser } from '../../../../hooks';
import { COUNTRIES } from '../../../../utils/countries';

const formatDate = (dateString) => {
  return format(new Date(dateString), 'yyyy-MM-dd');
};

const UpdateProfileForm = () => {
  const { currentUser, isCurrentUserLoading, isCurrentUserError } =
    useGetCurrentUser();
  const updateProfileFormValidation = useUpdateProfileFormValidation();
  const formikRef = useRef(null);
  const { submitUpdateProfileForm, isPending } = useUpdateProfileFormSubmit();
  const { t } = useTranslation();

  const [isEditing, setIsEditing] = useState(false);
  const [initialFormValues] = useState<IUpdateProfileForm>({
    lastname:
      !isCurrentUserLoading && !isCurrentUserError
        ? currentUser.lastname || ''
        : '',
    firstname:
      !isCurrentUserLoading && !isCurrentUserError
        ? currentUser.firstname || ''
        : '',
    dateOfBirth:
      !isCurrentUserLoading && !isCurrentUserError
        ? formatDate(currentUser.dateOfBirth) || ''
        : '',
    country:
      !isCurrentUserLoading && !isCurrentUserError
        ? currentUser.address.country || ''
        : '',
    phone:
      !isCurrentUserLoading && !isCurrentUserError
        ? currentUser.phone || ''
        : '',
    email:
      !isCurrentUserLoading && !isCurrentUserError
        ? currentUser.email || ''
        : '',
    isSubscribeNewsletter:
      !isCurrentUserLoading && !isCurrentUserError
        ? currentUser.isSubscribeNewsletter || false
        : false,
  });

  const onSubmit = async (values: IUpdateProfileForm) => {
    const formattedValues = {
      ...values,
      dateOfBirth: formatISO(
        parse(values.dateOfBirth, 'yyyy-MM-dd', new Date()),
      ),
      country:
        COUNTRIES.find((c) => c.title === values.country)?.value ||
        values.country,
    };

    submitUpdateProfileForm(formattedValues);
    setIsEditing(false);
  };

  const handleEditClick = () => {
    setIsEditing(true);
  };

  const handleCancelClick = () => {
    if (formikRef.current) {
      formikRef.current.resetForm();
    }
    setIsEditing(false);
  };

  return (
    <Formik
      innerRef={formikRef}
      enableReinitialize
      initialValues={initialFormValues}
      validationSchema={updateProfileFormValidation}
      onSubmit={onSubmit}
    >
      {(formik) => (
        <Form>
          <div className="grid md:grid-cols-2 gap-4 my-4">
            <label htmlFor="lastname" className="text-white">
              {t('auth.createAccount.input.lastName.placeholder')}
            </label>
            <LastnameField formik={formik} disabled={!isEditing} />

            <label htmlFor="firstname" className="text-white">
              {t('auth.createAccount.input.firstName.placeholder')}
            </label>
            <FirstnameField formik={formik} disabled={!isEditing} />

            <label htmlFor="birthdate" className="text-white">
              {t('auth.createAccount.input.dateOfBirth.placeholder')}
            </label>
            <BirthdateField formik={formik} disabled={!isEditing} />

            <label htmlFor="country" className="text-white">
              {t('auth.createAccount.input.country.placeholder')}
            </label>
            <CountryField formik={formik} disabled={!isEditing}/>

            <label htmlFor="phone" className="text-white">
              {t('auth.createAccount.input.phone.placeholder')}
            </label>
            <PhoneField formik={formik} disabled={!isEditing} />

            <label htmlFor="email" className="text-white">
              {t('auth.createAccount.input.email.placeholder')}
            </label>
            <EmailField formik={formik} disabled={true} />
          </div>

          {isEditing ? (
            <div className="flex space-x-4 mt-4">
              <Button
                variant="outline"
                className="px-6 py-3"
                type="button"
                onClick={handleCancelClick}
              >
                {t('home.navigation.form.cancel')}
              </Button>
              <Button
                className="px-6 py-3"
                type="submit"
                isLoading={isPending}
                disabled={!formik.dirty}
              >
                {t('home.navigation.form.save')}
              </Button>
            </div>
          ) : (
            <Button
              className="mt-4 px-6 py-3"
              type="button"
              onClick={handleEditClick}
            >
              {t('home.navigation.form.edit')}
            </Button>
          )}

          <div className="mt-4">
            <IsSubscribeNewsletterField formik={formik} disabled={!isEditing} />
          </div>
        </Form>
      )}
    </Formik>
  );
};

export default UpdateProfileForm;
import React, { useId } from 'react';
import { Field, FormikProps } from 'formik';
import { useTranslation } from 'react-i18next';
import { IUpdateProfileForm } from '../../types';
import CountrySelector from './CountrySelector';

interface CountryFieldProps {
  formik: FormikProps<IUpdateProfileForm>;
  disabled?: boolean;
}

const CountryField = ({ formik, disabled }: CountryFieldProps) => {
  const { t } = useTranslation();
  const { errors, touched } = formik;
  const id: string = useId();

  return (
    <Field
      component={CountrySelector}
      id={id}
      name="country"
      placeholder={t('auth.createAccount.input.country.placeholder')}
      required
      disabled={disabled}
      helperText={touched.country && errors.country}
      error={errors.country && touched.country}
      className="w-full"
    />
  );
};

export default CountryField;
import React, { useState } from 'react';
import { FlagIcon, FlagIconCode } from 'react-flag-kit';
import { FieldProps } from 'formik';
import { HelperText, InputProps, MenuItem, Select } from '@monorepo/kit-ui';
import { ICountry } from '../../../../types';
import { COUNTRIES } from '../../../../utils/countries';

const CountrySelector = ({ field, ...props }: InputProps & FieldProps) => {
  const [countries, setCountries] = useState<ICountry[]>(COUNTRIES);

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    const value = event.target.value.toLowerCase();
    const filteredCountries = COUNTRIES.filter((c) =>
      c.title.toLowerCase().includes(value),
    );
    const exactMatch = COUNTRIES.find((c) => c.title.toLowerCase() === value);
    setCountries(filteredCountries);
    if (exactMatch) {
      field.onChange({
        target: { value: exactMatch.value, name: field.name },
      } as React.ChangeEvent<HTMLInputElement>);
    } else {
      field.onChange(event);
    }
  };

  return (
    <div className="gap-1.5">
      <Select
        {...props}
        value={field.value}
        defaultValue={COUNTRIES.find((c) => c.value === field.value)?.title}
        name={field.name}
        onChange={handleChange}
        onBlur={field.onBlur}
        readOnly={false}
      >
        {countries.length === 0
          ? null
          : countries.map((country, index) => (
              <MenuItem key={index} value={country.title}>
                <div className="inline-flex gap-4 items-center">
                  <FlagIcon
                    code={country.value as FlagIconCode}
                    className="w-6 h-4"
                  />
                  {country.title}
                </div>
              </MenuItem>
            ))}
      </Select>
      {props.helperText && (
        <HelperText helperText={props.helperText} isError={props.error} />
      )}
    </div>
  );
};

export default CountrySelector;

I would like that when clicking on “Cancel”, the name and value of the field are reset with the initial values ​​of currentUser.address.country (for the country code) and therefore COUNTRIES.find((c) => c. value === currentUser.address.country)?.title for the name of the Country
What is the best way to do this?

Theme wordpress giá rẻ Theme wordpress giá rẻ Thiết kế website

LEAVE A COMMENT