Formik validations not working after adding errors and touched - reactjs

Below I have shown my Formik validations via "errors , touched". However no errors are showing up if I try to submit the form
return (
<div>
{loading && "Loading..."}
<Formik
initialValues={{
title: 'Software developer',
}}
onSubmit={handleSubmit}>
Here I am passing in errors and touched as provided by the Formik tags started above
{({ errors, touched }) => (
<Form>
<Field name="title">
{({ field, form }) => (
<label className="mt-3 block">
<span className="text-gray-700">Title</span>
<input
{...field}
type="text"
placeholder="Software developer"
style={
form.touched.title && form.errors.title ? (
{ border: '2px solid var(--primary-red)' }
) : null
}
/>
</label>
)}
</Field>
<button type="submit">Submit</button>
</Form>
)}
</Formik>
</div>
)

Related

Populate react formik form with existing data

i am new to react, can anyone explain to me how can i manipulate or repopulate my existing form from backend data in react.
I am trying to edit and existing item in the inventory that i wanna change values for. i am using formik with react and formik grid. for data i am using AXIOS.
What i am trying to do is to get edit a specific entry from my database which has changed values. it's like trying to update values
<Formik
validationSchema={schema}
initialValues={{
name: "",
numberOfSets: "0",
sortValue: "0",
boxType: "",
price: "",
photo: "",
}}
onSubmit={({
name,
numberOfSets,
sortValue,
boxType,
price,
photo,
}) => {
boxService.addBox(
name,
numberOfSets,
sortValue,
boxType,
price,
photo
);
alert("Box added Successfully!"); // Box or Gift it's same thing
window.location.reload(false);
}}
>
{({
values,
errors,
touched,
handleBlur,
handleSubmit,
setFieldValue,
}) => {
return (
<Form
form={form}
name="edit-gift"
onFinish={handleSubmit}
{...layout}
labelAlign="left"
>
// These are the fields i am trying to manipulate
<Form.Item name="name" label="Name">
<Input
name="name"
title="Product Name"
dataIndex="name"
key="productName"
value={values.name}
onChange={(e) => setFieldValue("name", e.target.value)}
onBlur={handleBlur}
placeholder="Please enter Box Name"
/>
{errors?.name && touched?.name && (
<Text type="danger">{errors?.name}</Text>
)}
</Form.Item>
<Form.Item name="numberOfSets" label="Number of Sets">
<Input
name="numberOfSets"
type="number"
value={values.numberOfSets}
onChange={(e) =>
setFieldValue("numberOfSets", e.target.value)
}
onBlur={handleBlur}
placeholder="Please enter Number of Sets"
/>
{errors?.numberOfSets && touched?.numberOfSets && (
<Text type="danger">{errors?.numberOfSets}</Text>
)}
</Form.Item>
<Form.Item name="sortVlaue" label="Sort Value">
<Input
name="sortVlaue"
type="number"
value={values.sortValue}
onChange={(e) => setFieldValue("sortVlaue", e.target.value)}
onBlur={handleBlur}
placeholder="Please enter soring value"
/>
{errors?.numberOfBoxes && touched?.numberOfBoxes && (
<Text type="danger">{errors?.numberOfBoxes}</Text>
)}
</Form.Item>
<Form.Item name="boxType" label="Type">
<Select
value={values.boxType}
onChange={(value) => setFieldValue("boxType", value)}
onBlur={handleBlur}
placeholder="Please enter Box Type"
>
<Select.Option value="reward">Reward</Select.Option>
<Select.Option value="doublerandom">
Double Random
</Select.Option>
</Select>
{errors?.boxType && (
<Text type="danger">{errors?.boxType}</Text>
)}
</Form.Item>
<Form.Item name="price" label="Price">
<Input
name="price"
title="Product Price"
dataIndex="price"
key="price"
value={values.price}
onChange={(e) => setFieldValue("price", e.target.value)}
onBlur={handleBlur}
placeholder="Please enter Box Price"
/>
{errors?.price && touched?.price && (
<Text type="danger">{errors?.price}</Text>
)}
</Form.Item>
<Form.Item name="photo" label="Product Picture">
<div className="dropzone-container">
{values.photo && <img src={values.photo} alt=""></img>}
{!values.photo && (
<Dropzone
onDrop={(acceptedFiles) => {
acceptedFiles.map((file) => {
console.log(file);
});
let fr = new FileReader();
fr.onload = function () {
setFieldValue("photo", fr.result);
setFieldValue("imgName", acceptedFiles[0].name);
console.log(acceptedFiles[0]);
};
fr.readAsDataURL(acceptedFiles[0]);
}}
accept={{ "image/*": [] }}
maxSize={1000000}
>
{({ getRootProps, getInputProps }) => (
<section>
<div {...getRootProps({ style })}>
<input {...getInputProps()} />
<p>
Drag 'n' drop some files here, or click to
select files
</p>
<aside>
Tips: The size ratio of the photo is: 750:216,
the maximum recommended size is 1M, and the
format is: .jpg, .jpeg, .png
</aside>
</div>
</section>
)}
</Dropzone>
)}
</div>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
Cofirm save
</Button>
</Form.Item>
</Form>
);
}}
</Formik>
You could either:
rerender the Formik component when your data is available and pass it to the initialValues prop by doing something like
results?.data && <Formik initialValues={{...}}>...</Formik>
or set the values manually with setValues after the data is available
const {setValues, values, ...} = useFormik({...});
useEffect(() => {
setValues(results?.data); // use any fields from your data
}, [results]} // this is the data from your api

Why can't I get values of Date and Text Area in Formik?

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 value of Date and Text Area elements and they appear blank on Console. How can I solve this out?
Here I define the intial values.
const initialValues = {
jobTitle: { id: "" },
deadline: "",
description: "",
};
Then here I try to get the values from form element
return (
<div>
<Card fluid>
<Card.Content>
<Card.Header>Create A New Job Ad</Card.Header>
<Divider inverted />
<Formik
initialValues={initialValues}
validationSchema={jobAdCreateSchema}
onSubmit={(values) => {
handleSubmit(values);
}}
>
{({ values, setFieldValue }) => (
<div>
<pre>{JSON.stringify(values, undefined, 2)}</pre>
<Form className="ui form">
<FormField>
<label>Job Title</label>
<Dropdown
selection
placeholder="Select a Job Title"
name="jobTitle"
fluid
options={jobTitleOption}
value={values.jobTitle.id}
onChange={(_, { value }) =>
setFieldValue("jobTitle.id", value)
}
/>
</FormField>
<FormField>
<label>Application Deadline</label>
<input
name="deadline"
style={{ width: "100%" }}
type="date"
placeholder="Application Deadline"
value={values.deadline}
onChange={formik.handleChange}
/>
</FormField>
<FormField>
<label>Job Description</label>
<TextArea
name="description"
placeholder="Job Description"
style={{ minHeight: 100 }}
value={values.description}
onChange={formik.handleChange}
/>
</FormField>
<FormField>
<Button color="green" type="submit">
Submit
</Button>
</FormField>
</Form>
</div>
)}
</Formik>
</Card.Content>
</Card>
</div>
);
formik isn't defined, so your assigning an onChange function that doesn't exist.
Destructure handleChange from the argument, then assign it to the inputs like so:
{({ values, setFieldValue, handleChange }) => (
//...
<input
name="deadline"
style={{ width: "100%" }}
type="date"
placeholder="Application Deadline"
value={values.deadline}
onChange={handleChange}
/>
)}
Live demo

formik render props has been deprecated and will be deprecated in future versions

I just started using formik and i am using old codebase to write some code.
With this code I get this error:
<Formik
enableReinitialize={true}
initialValues={InitialValues}
onSubmit={(formData, formikProps) => this.handleSubmit(formData, formikProps)}
render={formikProps => (
<View>
<FieldArray
name="address"
render={arrHelpers => (
<View>
{formikProps.values.address &&
formikProps.values.address.length > 0 &&
formikProps.values.address.map((item, index) =>
this.renderForm(item, index, arrHelpers, formikProps)
)}
</View>
)}
/>
<TouchableOpacity onPress={formikProps.handleSubmit} style ={styles.buttonDown}>
<Text style={styles.submitButton}>Submit</Text>
</TouchableOpacity>
</View>
)}
/>
Check this out: https://formik.org/docs/migrating-v2#all-render-props-have-been-deprecated-with-a-console-warning
Instead of using a render prop, you would pass your render function as a child (as shown in the link above):
- <Field name="firstName" render={props => ....} />
+ <Field name="firstName">{props => ... }</Field>
Just close tags from <Formik> ...props... </Formik> and don't put inside the open tag from Formik. Be attention after, because you don't need more the "render=" and you need to put your "props" inside parenthesis.
Like this...
<Formik
enableReinitialize={true}
initialValues={InitialValues}
onSubmit={(formData, formikProps) => this.handleSubmit(formData, formikProps)}>
{({formikProps}) => (
<View>
<FieldArray
name="address"
{({arrHelpers}) => (
<View>
{formikProps.values.address &&
formikProps.values.address.length > 0 &&
formikProps.values.address.map((item, index) =>
this.renderForm(item, index, arrHelpers, formikProps)
)}
</View>
)}
/>
<TouchableOpacity onPress={formikProps.handleSubmit} style={styles.buttonDown}>
<Text style={styles.submitButton}>Submit</Text>
</TouchableOpacity>
</View>
)}
</Formik>
For Fields use the same way as the before answer.
In resume, just replace
<Formik render={(props) => ...} /> to <Formik>{(props) => ...}</Formik>
Another example (more simple):
<Formik
onSubmit={onSubmit}
initialValues={{
name: '',
email: ''
}}
>
{({ values }) => (
<div className="container">
<h1>Formulário Formik de exemplo</h1>
<Form>
<div>
<label>Nome</label>
<Field name="name" type="text" />
</div>
<div>
<label>Email</label>
<Field name="email" type="email" />
</div>
<button className="btnSubmit" type="submit">Save</button>
</Form>
</div>
)}
</Formik>
In this link: enter link description here you can get documentation about that.
with the use of spread, follow the example.
{ ...values => (
<div className="container">
<h1>Formulário Formik de exemplo</h1>
<Form>
<div>
<label>Nome</label>
<Field name="name" type="text" />
</div>
<div>
<label>Email</label>
<Field name="email" type="email" />
</div>
<button className="btnSubmit" type="submit">Save</button>
</Form>
</div>
)}

Formik Validation of semantic-ui-react select-field(dropdown)

Hi guys i would like to validate semantic-ui form with a selectInput (dropdown) but it brings a warning and it does not work. Here is the warning:
Formik called handleChange, but you forgot to pass an "id" or "name" attribute to your input:
<div role="option" aria-checked="false" aria-selected="false" class="item" style="pointer-events: all;"><span class="text">value Two</span></div>Formik cannot determine which value to update.
Formik validates the textInput properly but for the selectInput it brings the above warning and nothing is taken in the handleSubmit function.
Below is the snip of the code please.
<Formik
initialValues={{ levelValue: "", attachLevel: "" }}
validationSchema={Yup.object({
levelValue: Yup.string().required("Required Please"),
attachLevel: Yup.string().required("Required Please")
})}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
setSubmitting(false);
}, 400);
}}
>
{({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
isSubmitting
}) => (
<Form onSubmit={handleSubmit}>
<Form.Group>
<Form.Input
name="levelValue"
placeholder="Define Level..."
onChange={handleChange}
onBlur={handleBlur}
value={values.levelValue}
type="text"
/>
{touched.levelValue && errors.levelValue ? (
<span className="span_error">
{errors.levelValue}
</span>
) : null}
</Form.Group>
<Form.Group>
<Form.Input
control={Select}
name="attachLevel"
onChange={handleChange}
onBlur={handleBlur}
defaultValue={values.attachLevel}
multiple
options={Class}
/>
{touched.attachLevel && errors.attachLevel ? (
<span className="span_error">
{errors.attachLevel}
</span>
) : null}
</Form.Group>
<Button
color="blue"
type="submit"
className="submit"
disabled={isSubmitting}
>
<Icon name="add" />
Attach
</Button>
</Form>
)}
</Formik>
Any Help will be appreciable please....

props.mutators is deprecated

My code is working, but I got a warning :
Warning: As of React Final Form v3.3.0, props.mutators is deprecated
and will be removed in the next major version of React Final Form.
Use: props.form.mutators instead. Check your ReactFinalForm render
prop.
with this exemple :
https://codesandbox.io/s/kx8qv67nk5
return <Form
onSubmit={() => console.log('ok')}
mutators={{
...arrayMutators
}}
initialValues={ {customers: [{firstName: 'a', lastName: 'b'}]} }
render={({
handleSubmit,
mutators: { push, pop }, // injected from final-form-arrays above
pristine,
reset,
submitting,
values
}) => {
return (
<form onSubmit={handleSubmit}>
<div className="buttons">
<button
type="button"
onClick={() => push('customers', undefined)}>
Add Customer
</button>
</div>
<FieldArray name="customers">
{({ fields }) =>
fields.map((name, index) => (
<div key={name}>
<label>Cust. #{index + 1}</label>
<Field
name={`${name}.firstName`}
component="input"
placeholder="First Name"
/>
<Field
name={`${name}.lastName`}
component="input"
placeholder="Last Name"
/>
<GithubField name="user1" onSearch={(item) => {
this.api.getByFirstname(item).then(result => console.log(result));
}} />
<span
onClick={() => fields.remove(index)}
style={{ cursor: 'pointer' }}>❌</span>
</div>
))}
</FieldArray>
<div className="buttons">
<button type="submit" disabled={submitting || pristine}>
Submit
</button>
<button
type="button"
onClick={reset}
disabled={submitting || pristine}>
Reset
</button>
</div>
<pre>{JSON.stringify(values, 0, 2)}</pre>
</form>
)
}}
/>
How to do the right way ?
The warning already tells you what to do.
You must use form.mutators instead of just mutators
To do so, you can change your code from
mutators: { push, pop }
to
form: { mutators: { push, pop } }

Resources