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?