onchange in a form using formik the value of the field is not updated - reactjs

I'm new to react, and I'm trying to apply validations to a form.
For some reason when adding the property:
onChange={onChange}
I want to send the values to the parent component. That's why I'm using the onchange.
Nothing I write is shown in my text fields, why does this happen?
export const Son = props => {
const { onChange } = props;
return (
<Formik
initialValues={{
fullname: "",
email: ""
}}
validationSchema={Yup.object().shape({
fullname: Yup.string()
.min(2, "Your name is too short")
.required("Please enter your full name"),
email: Yup.string()
.email("The email is incorrect")
.required("Please enter your email")
})}
onSubmit={(values, { setSubmitting }) => {
const timeOut = setTimeout(() => {
console.log(values);
setSubmitting(false);
clearTimeout(timeOut);
}, 1000);
}}
>
{({
values,
errors,
touched,
handleSubmit,
isSubmitting,
validating,
valid
}) => {
return (
<Form name="contact" method="post" onSubmit={handleSubmit}>
<label htmlFor="fullname">
Fullname
<Field
type="text"
name="fullname"
autoComplete="name"
placeholder="your fullname"
onChange={onChange}
/>
</label>
{<ErrorMessage name="fullname">{msg => <p>{msg}</p>}</ErrorMessage>}
{/*errors.fullname && touched.fullname && <p>{errors.fullname}</p>*/}
<br />
<label htmlFor="email">
Email
<Field
type="email"
name="email"
autoComplete="email"
placeholder="your email"
onChange={onChange}
/>
</label>
<ErrorMessage name="email">{msg => <p>{msg}</p>}</ErrorMessage>
<br />
<button type="submit" disabled={!valid || isSubmitting}>
{isSubmitting ? `Submiting...` : `Submit`}
</button>
</Form>
);
}}
</Formik>
);
};
this is my live code:
https://stackblitz.com/edit/react-qotvwb?file=components/son_component.js

you're not using the formik handleChange at all.
I highlighted the changes that I made in https://stackblitz.com/
and you can test this working here

Related

How to set the formik field value with the useState hook?

I have a simple form which has only two fields,name and wallet_address, I want the user's to type wallet_address or simply scan the address, once the scan is successful the address will be stored in the state variable, I want to update the wallet_address field with the new state value. Currently this is not working, only manually typing the address is working but not the scanning feature.
import { ErrorMessage, Field, Form, Formik } from "formik";
import ScanQrPopUp from "../components/wallet/popup/ScanQrPopup";
const [walletAddress, setWalletAddress] = useState<any>("");
const handleScanAddress = (wallet: string) => {
console.log("wallet address---", wallet);
setWalletAddress(wallet);
};
const validationSchema = Yup.object().shape({
name: Yup.string()
.min(3, "Name should be atleast 3 characters")
.required("Name is required"),
wallet_address: Yup.string()
.required("Wallet Address is required")
});
<Formik
initialValues={{
name: "",
wallet_address: "",
}}
onSubmit={async (values, { resetForm }) => {
setIsLoading(true);
console.log(values.name);
console.log(values.wallet_address);
setIsLoading(false);
resetForm();
}}
validationSchema={validationSchema}
validateOnChange
>
{({ values, resetForm }) => (
<Form>
<div className="w-[80%]">
<label
className="text-left"
htmlFor="input"
>
Name
</label>
<Field
name="name"
type="text"
spellCheck={false}
className="block"
placeholder="Enter the Name"
/>
<p className="text-red-600">
<ErrorMessage name="name" />
</p>
</div>
<div className="w-[80%] mt-4">
<label
className="text-left"
htmlFor="wallet_address"
>
wallet address
</label>
<Field
name="wallet_address"
type="text"
spellCheck={false}
className="block "
placeholder="Enter wallet address"
/>
<p className="text-red-600 ">
<ErrorMessage name="wallet_address" />
</p>
</div>
</Form>
)}
</Formik>
<ScanQrPopUp
handlePopUp={handleQrPopup}
walletAddress={handleScanAddress}
/>

sweetalert pop up if passwords don't match

I want to make good pop up to my project with sweetalert when the passwords don't match:
const SignUp = ({ signUpStart, userError, resetError }) => {
const [userCredentials, setUserCredentials] = useState({
displayName: "",
email: "",
password: "",
confirmPassword: "",
});
const { displayName, email, password, confirmPassword } = userCredentials;
const handleSubmit = async (event) => {
event.preventDefault();
if (password !== confirmPassword) {
alert(`password don't match`);
return;
}
signUpStart({ displayName, email, password });
};
const handleChange = (event) => {
const { name, value } = event.target;
setUserCredentials({ ...userCredentials, [name]: value });
};
return (
<div className="signup">
<h2 className="title">I do not have a account</h2>
<span>Sign up with your email </span>
<form className="sign-up-form" onSubmit={handleSubmit}>
<Form
type="text"
name="displayName"
value={displayName}
onChange={handleChange}
label="Display Name"
required
></Form>
<Form
type="email"
name="email"
value={email}
onChange={handleChange}
label="Email"
required
></Form>
<Form
type="password"
name="password"
value={password}
onChange={handleChange}
label="Password"
required
></Form>
<Form
type="password"
name="confirmPassword"
value={confirmPassword}
onChange={handleChange}
label="Confirm Password"
required
></Form>
<CustomButton type="submit">SIGN UP</CustomButton>
</form>
{userError && userError.message ? (
<SweetAlert
show={!!userError.message}
type="warning"
title="Something went wrong"
text={userError.message}
onConfirm={() => resetError()}
/>
) : null}
</div>
);
};
EDIT: i add my whole component to the question. i deleted my mapstatetoprops and dispatch.
So i basically want to run once when i hit my submit button.
I want to make the alert in the if statement. But I think I need to refactor little. Can anyone help with this?

How to disable button on submit form in formik?

I have a form in my react component with handleSubmit. What I need to do is when I submit the form(on save click) the save button automatically should get disabled and when I get the response it automatically gets enabled.
handleSubmit = async({ company, email }, { setSubmitting, setErrors }) => {
setSubmitting(true)
const { value: { status, message } } = await this.props.createCompany({ name: company, email })
if (status) {
this.fetchCompanies()
this.closeModal()
} else {
setErrors({ email: message })
}
}
<Formik
initialValues={loginDetails}
validationSchema={loginSchema}
onSubmit={(values, formikProps) => this.handleSubmit(values, formikProps)}
>
{({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
isSubmitting
}) => (
<form onSubmit={handleSubmit}>
<div className="col-md-12">
<div className="form-group material-textfield">
<input type="text" name="email" value={values.email} onChange={handleChange} className="form-control material-textfield-input"/>
<ErrorMessage component="span" name="email" className="invalid-feedback d-block"/>
<label className="material-textfield-label">Email<span>*</span></label>
</div>
</div>
<button type="submit" className="btn btn-dark btn-lg w-100" disabled={isSubmitting}>Save</button>
</form>
)}
</Formik>
And for this I have used setSubmitting function from formik. But it doesn't work.
Kindly help.
This should help:
const onSubmitHandler = (values, formik) => {
persistYourData(values).then(r => {
formik.setSubmitting(false);
}).catch(error => console.log(error));
}
...
<Button variant="contained" color={"primary"} onClick={pr.handleSubmit} disabled={ ((!(pr.isValid && pr.dirty)) || pr.isSubmitting) }>Submit</Button>
#You can disable the button with **formik.isSubmitting** or **formik.errors** #
<Formik
initialValues={{
email: '',
password: '',
}}
validationSchema={Yup.object({
email: Yup.string().email('Invalid email address').required('Required'),
password: Yup.string().required('Required'),
})}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
setSubmitting(false);
});
}}
>
{(formik) => (
<Form>
<h1>Login</h1>
<Field type='email' name='email' />
<br />
<ErrorMessage name='email' />
<br />
<Field type='password' name='password' />
<br />
<ErrorMessage name='password' />
<br />
<button disabled={formik.isSubmitting || formik.errors}>Login</button>
</Form>
)}
</Formik>

Formik number field accept only positive numbers

I have a form in which I have a number field. I am using formik for this. I need to have an input which only accepts positive numbers.
This is the codesandbox url
You should use regex in onChange event of Number input
Sample code:
const App = () => (
<div className="app">
<Formik
initialValues={{ email: "", rank: -2 }}
onSubmit={async values => {
await new Promise(resolve => setTimeout(resolve, 500));
alert(JSON.stringify(values, null, 2));
}}
validationSchema={Yup.object().shape({
email: Yup.string()
.email()
.required("Required")
})}
>
{props => {
const {
values,
touched,
errors,
dirty,
isSubmitting,
handleChange,
handleBlur,
handleSubmit,
handleReset,
setFieldValue
} = props;
return (
<form onSubmit={handleSubmit}>
<label htmlFor="email" style={{ display: "block" }}>
Email
</label>
<input
id="email"
placeholder="Enter your email"
type="text"
value={values.email}
onChange={handleChange}
onBlur={handleBlur}
className={
errors.email && touched.email
? "text-input error"
: "text-input"
}
/>
<label htmlFor="email" style={{ display: "block" }}>
Rank
</label>
<input
id="rank"
placeholder="Enter your email"
type="number"
value={values.rank}
onChange={e => {
e.preventDefault();
const { value } = e.target;
const regex = /^(0*[1-9][0-9]*(\.[0-9]*)?|0*\.[0-9]*[1-9][0-9]*)$/;
if (regex.test(value.toString())) {
setFieldValue("rank", value);
}
}}
onBlur={handleBlur}
/>
<button type="submit" disabled={isSubmitting}>
Submit
</button>
</form>
);
}}
</Formik>
</div>
);
render(<App />, document.getElementById("root"));
Code sanbox link: https://codesandbox.io/embed/formik-example-nut8p?fontsize=14&hidenavigation=1&theme=dark
You can add the attribute min to your input
<input
id="rank"
placeholder="Enter your rank"
type="number"
value={values.rank}
min="1"
onChange={handleChange}
onBlur={handleBlur}
/>
Pass a validate function
// Synchronous validation
const validate = values => {
const errors = {};
if (!values.numberFied < 0) {
errors.numberFied = 'Must be positive';
}
//...
return errors;
};

How to add Radio Button in Formik Validations Reactjs?

I am using Formik for Validating my Registration form I want to add validate gender via radio button how can I do that. I am not able to add radio button.
This is what I have done:-
const SignupSchema = Yup.object().shape({
email: Yup.string()
.email('Invalid email')
.required('Required'),
password: Yup.string()
.min(4, 'Password Must be four characters long!')
.max(20, 'Too Long!')
.required('Required'),
});
class Register extends Component {
render() {
return (
<Formik
initialValues={{
email: '',
password:'',
gender:'',
}}
validationSchema={SignupSchema}
onSubmit={values => {
console.log(values);
}}
>
{({ errors, touched }) => (
<Form>
<Field style={customStyles.textfield} placeholder="Email" name="email" type="email" />
{errors.email && touched.email ? <div}>{errors.email}</div> : null}
<Field placeholder="Enter Password" name="password" type="password" />
{errors.password && touched.password ? <div >{errors.password}</div> : null}
<button type="submit">Submit</button>
</Form>
)}
</Formik>
</div>
)
}
}
change gender initialValues as male
<Field
name="gender"
render={({ field }) => (
<>
<div className="radio-item">
<input
{...field}
id="male"
value="male"
checked={field.value === 'male'}
name="type"
type="radio"
/>
<label htmlFor="male">Male</label>
</div>
<div className="radio-item">
<input
{...field}
id="female"
value="female"
name="type"
checked={field.value === 'female'}
type="radio"
/>
<label htmlFor="female">Female</label>
</div>
</>
)}
/>
This solution gives you the chance to have more than 2 options.
Let say you have a file called Main.js and you want to put a radio button input in it. First, provide a list of options for your radio button in the Main.js
const radioOptions = [
{ key: 'Option 1', value: 'value 1' },
{ key: 'Option 2', value: 'value 2' },
{ key: 'Option 3', value: 'value 3' }
];
Next, create a RadioButton.js file with below code
import React from 'react';
import { Field } from 'formik';
const RadioButton = (props) => {
const { label, name, options, ...rest } = props;
return (
<div>
<label htmlFor={name}>{label}</label>
<Field name={name} {...rest} >
{
({ field }) => {
return options.map(option => {
return (
<React.Fragment key={option.key}>
<input
type='radio'
id={option.id}
{...field}
value={option.value}
checked={field.value === option.value}
/>
<label htmlFor={option.id}>{option.key}</label>
</React.Fragment>
);
})
}
}
</Field>
</div>
);
};
export default RadioButton;
Then put the reusable RadioButton Component in the Main.js wherever you want the radio button input to render.
The result UI will be 3 radio buttons with values "value 1", "value 2" and "value 3".
You can check out this awesome youtube series to know more.
This can be done simply but using this code below. it worked for me:
You will need to import Formik from "formik"
<Formik
initialValues={{
email: '',
password:'',
gender:'',
}}
// validations
validationSchema={SignupSchema}
onSubmit={values => { console.log(values); }}
>
{(formik) => (
<Form onSubmit={formik.handleSubmit}>
//Your Other inputs........
<div className="custom-control">
<input
id="male"
type="radio"
value="male"
name='gender'
onChange={formik.handleChange}
defaultChecked={formik.values.gender=== "male"}
/>
<label
className="custom-control-label"
htmlFor="male"
>
Male
</label>
</div>
<div className="custom-control">
<input
id="female"
type="radio"
value="female"
name='gender'
onChange={formik.handleChange}
defaultChecked={formik.values.gender=== "female"}
/>
<label
className="custom-control-label"
htmlFor="female"
>
Female
</label>
</div>
//Your Other inputs......
<button type="submit">Submit</button>
</Form>
)}
</Formik>

Resources