Form not Submitting in React using Formik and Yup - reactjs

I'm using Autocomplete component in Material UI and I'm using Formik and Yup for validations.
My problem is that when I submit my values and console it. It doesn't appear which means it doesn't conform to its yup validation.
Pls check my codesandbox here
Click here
<Formik
validationSchema={citySchema}
initialValues={{ city_id: [{ id: null, name: "" }] }}
onSubmit={submit}
>
{({ handleChange, values, setFieldValue, touched, errors }) => (
<Form>
<Autocomplete
id="city_id"
name="city_id"
options={cities}
getOptionLabel={(option) => option.name}
style={{ width: 300 }}
onChange={(e, value) => {
setFieldValue("city_id", value);
}}
renderInput={(params) => (
<TextField
label="City"
variant="outlined"
helperText={touched.city_id && errors.city_id}
error={touched.city_id && Boolean(errors.city_id)}
{...params}
/>
)}
/>
<Button variant="contained" color="primary" type="submit">
Submit
</Button>
</Form>
)}
</Formik>

Your validationSchema requires a name but your code never supplies it.
Either make it optional or add a name input field.
An easy way to debug this is to print out the errors formik is supplying you:
<Form>
<pre>{JSON.stringify(errors, null, 2)}</pre>
<Autocomplete
...

Related

Formik Default Values UseEffect

I am trying to prepopulate a Formik with JSON data. The data appears fine and it is returned. I have two issues.
I am using ASP.NET Core as the back end. Should I use values or initialValues as the variable? When I use initialValues, I get assign fields. The labels are still populated.
The labels are still populated, after I send a default value. All the fields are read only and I cannot edit them:
Here is my code:
function OrdersToReporting() {
const [initialValues, setInitialValues] = useState<OrdersToReportingViewModels>({ });
useEffect(() => {
agent.Settings.getOrdersSettings().then((userList) => {
let solutionName = (new URLSearchParams(window.location.search)).get("SolutionName");
let solutionWebsite = (new URLSearchParams(window.location.search)).get("SolutionWebsite");
userList.data.SolutionName = solutionName;
userList.data.SolutionWebsite = solutionWebsite;
setInitialValues(userList.data);
});
}, []);
const handleSubmit = async (
values: any,
{ resetForm, setErrors, setStatus, setSubmitting }: any
) => {
try {
await timeOut(1500);
agent.Settings.saveOrdersSettings(values);
resetForm();
setStatus({ sent: true });
setSubmitting(false);
} catch (error: any) {
setStatus({ sent: false });
setErrors({ submit: error.message });
setSubmitting(false);
}
};
return (
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={handleSubmit}
>
{({
errors,
handleBlur,
handleChange,
handleSubmit,
isSubmitting,
touched,
values,
status,
}) => (
{isSubmitting ? (
<Box display="flex" justifyContent="center" my={6}>
<CircularProgress />
</Box>
) : (
<form onSubmit={handleSubmit}>
<Grid container spacing={6}>
<Grid item md={6}>
<TextField
name="SolutionName"
label="Solution Name"
value={initialValues.SolutionName}
fullWidth
onBlur={handleBlur}
onChange={handleChange}
variant="outlined"
my={2}
/>
<TextField
name="SolutionWebsite"
label="Solution Website"
value={initialValues.SolutionWebsite}
fullWidth
onBlur={handleBlur}
onChange={handleChange}
variant="outlined"
my={2}
/>
<TextField
name="lastDownloadUtc"
label="Last Download Date Start"
value={initialValues.LastDownloadUtc}
fullWidth
onBlur={handleBlur}
onChange={handleChange}
variant="outlined"
my={2}
/>
</Grid>
<Grid item md={6}>
<TextField
name="lastDownloadUtcEnd"
label="Last Download Date End"
value={initialValues.LastDownloadUtcEnd}
fullWidth
onBlur={handleBlur}
onChange={handleChange}
variant="outlined"
my={2}
/>
</Grid>
</Grid>
<Button
type="submit"
variant="contained"
color="primary"
mt={3}
>
Save changes
</Button>
</form>
)}
)}
</Formik>
);
}
For your questions,
You should use initialValues to assign default values to your fields.
since you are getting the data from some function, there might be a delay in setting initialValues. So pass enableReinitialize={true} in formik props.
You were not able to change the values because you set
value={initialValues.fieldName} // always value will be this unless you change initialValues state
for every textfield. Always this will be same even if you edit.
Just remove the value property formik will handle it by default.

How to set value in MUI Select on onChange in Formik?

I was facing some challenges while integrating Formik with the Select component of MUI, firstly, it didn't change the value on the onChange event and also was not showing any error messages , if I didn't select anything, so at last, I was able to find the solution and I have shared the answer below
Here, I am setting the value directly using formik.setFieldValue and passing the value to as we usually do, also to show error messages I have used FormHelperText from MUI
const formik = useFormik({
initialValues: {
user: '',
},
validationSchema: validationSchema,
onSubmit: (values) => {
alert(JSON.stringify(values, null, 2));
},
});
------------
<FormControl
fullWidth
size="small"
id="userType"
error={formik.touched.userType && Boolean(formik.errors.userType)}
>
<InputLabel id="user-type">User Type</InputLabel>
<Select
id="userType"
label="User Type"
name="userType"
value={formik.values.userType}
onBlur={formik.handleBlur}
onChange={(e) => formik.setFieldValue('userType', e.target.value as string)}
error={formik.touched.userType && Boolean(formik.errors.userType)}
>
<MenuItem value={'admin'}>Student</MenuItem>
<MenuItem value={'superAdmin'}>Recruiter</MenuItem>
</Select>
{formik.touched.password && (
<FormHelperText sx={{ color: 'error.main' }}>{formik.errors.userType}</FormHelperText>
)}
</FormControl>

How to apply Formik with Chakra in typescript?

I am trying to use following example on Chakra but using Typescript
<Formik
initialValues={{ name: "Sasuke" }}
onSubmit={(values, actions) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
actions.setSubmitting(false);
}, 1000);
}}
>
{(props) => (
<Form>
<Field name="name" validate={validateName}>
{/* Trouble in this line below*/}
{({ field, form }) => (
<FormControl
isInvalid={form.errors.name && form.touched.name}
>
<FormLabel htmlFor="name">First name</FormLabel>
<Input {...field} id="name" placeholder="name" />
<FormErrorMessage>
{form.errors.name}
</FormErrorMessage>
</FormControl>
)}
</Field>
<Button
mt={4}
colorScheme="teal"
isLoading={props.isSubmitting}
type="submit"
>
Submit
</Button>
</Form>
)}
</Formik>
How do I define "field" and "form" in Typescript ? is there a prop for that ? or should I just define those things in an interface ?
I was encountering the same problem and gave a look at the source code.
You should be able to use FieldInputProps<T> where T is the value type you expect and FormikProps<T> where T is the type definition of the values you expect.
E.g.
{({ field, form }: { field: FieldInputProps<string>, form: FormikProps<{ name: string, surname: string }> }) => {
...
}}

Why can't I read Dropdown values by Formik in React?

I am using Formik and Yup for a form control in react application. I use also Semantic UI. In the application, when I click the submit button, whereas I can read the values from FormField elements and see them on Console, I can not get the values from Dropdown elements and they appear blank on Console. How can I solve this out?
return (
<div>
<Card fluid>
<Card.Content>
<Card.Header>Create A New Job Ad</Card.Header>
<Divider inverted />
<Formik
initialValues={initialValues}
validationSchema={jobAdCreateSchema}
onSubmit={(values) => {
console.log(values);
}}
>
<Form className="ui form">
<label>Job Title</label>
<FormField>
<Field name="jobTitle" placeholder="Select a Job Title"></Field>
</FormField>
<FormField>
<label>City</label>
<Dropdown
name="city"
placeholder="Select a City"
fluid
selection
options={cityOption}
/>
</FormField>
<FormField>
<Button color="green" type="submit">
Submit
</Button>
</FormField>
</Form>
</Formik>
</Card.Content>
</Card>
</div>
);
The issue is with the way the Dropdown component is rendered currently. You need to make use of the setFieldValue provided by Formik to manually update the Formik state.
<Formik
initialValues={{
city: ""
}}
onSubmit={(values) => console.log(values)}
>
{({ values, setFieldValue }) => (
<div>
<pre>{JSON.stringify(values, undefined, 2)}</pre>
<Dropdown
selection
placeholder="Select a City"
options={[
{ value: "NY", text: "New York" },
{ value: "LA", text: "Los Angeles" },
{ value: "SF", text: "San Fransico" }
]}
value={values.city}
onChange={(value) => setFieldValue("city", value)}
/>
</div>
)}
</Formik>
Working Sandbox

formik fields are not getting value

I'm using Formik in my React and redux project, but Formik fields are not getting value and onChange field function not working!
this form is for editing a customer. I'm using Formik in another part of project and i don't have a problem. I don't know what to do?
<Formik
initialValues={props.selectedCustomer.id ? props.selectedCustomer : emptyCustomer}
validationSchema={customerValidationSchema}
onSubmit={async (values: ICustomer, actions: FormikActions<any>) => {
console.log(values)
try {
await postCustomer(values)
props.selectedCustomer.id ? enqueueSnackbar('success') : enqueueSnackbar('fail')
actions.resetForm()
getCustomers(pageNum, pageSize)
setAddDialog(false)
}
catch (error) {
enqueueSnackbar(error, { variant: 'default' })
}
}}
>
{() => (
<Form id="addCustomerForm">
<div id="addCustomerDiv" className={clsx({
[classes.noDisplay]: !addDialog
})}>
<Grid style={{marginRight: '0.5rem'}} container spacing={5}>
<Grid item xs={2}>
<Field
name="firstName"
render={({ field, form }: FieldProps<ICustomer>) => (
<TextField
margin="dense"
id="firstName"
label="firstName"
fullWidth
{...field}
error={form.errors.firstName && form.touched.firstName ? true : false}
/>
)}
/>
</Grid>
<Button
type='submit'
form="addCustomerForm"
color="primary"
variant="contained"
style={{marginTop: '3rem'}}
className={clsx({
[classes.noDisplay]: !addDialog
})}
>
submit
</Button>
</Grid>
</Grid>
</div>
</Form>
)}
</Formik>
what is the problem?
I added enableReinitialize in Formik component and it worked.

Resources