How to use useState hook in formik forms - reactjs

I am using formik form and to get make a modal on this form how can i use useState hook ?
FormReq = ({ values, errors, touched, handleChange, isSubmitting, handleBlur }) =>
(
<>
<div className="container">
<Modal email={values.email} password={values.password}/>
</div>
<Form>
<div className="container">
<div className="form">
<Field type="email" name="email" placeholder="Email" onChange={handleChange} onBlur={handleBlur} className="inputField"/>
<Field type="password" name="password" placeholder="Password" onChange={handleChange} className="inputField"/>
<span className="buttonsubmit">
<button disabled={isSubmitting}>Submit</button>
</span>
</div>
</div>
<div className="container errors">
{ touched.email && errors.email && <p>{errors.email}</p> }
{ touched.password && errors.password && <p>{errors.password}</p> }
</div>
</Form>
</>
)
const ContactUs = withFormik({
mapPropsToValues({ email, password}){
return{
email: email || '',
password: password || ''
}
},
validationSchema: Yup.object().shape({
email: Yup.string().email('Email not valid').required('Email is required'),
password: Yup.string().min(9, 'Password must be 9 characters or longer').required('Password is required')
}),
handleSubmit(values, { resetForm }){
console.log(values);
resetForm();
}
})(FormReq)

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}
/>

formik rendering an element when input field is clicked in react?

I am trying to make a simple login form i want to render an element when an input field is clicked . I have done this in normal react form by rendering an element by changing the value of a boolean variable to true and when the input is written if the user touch somewhere else then the element disapears . kind of toggle thing . but i don't know hoe to do this in formik. my code looks like this.
import React from "react";
import { Formik } from "formik";
import * as EmailValidator from "email-validator";
import * as Yup from "yup";
const ValidatedLoginForm = () => (
<Formik
initialValues={{ email: "", password: "" }}
onSubmit={(values, { setSubmitting }) => {
console.log(values);
console.log("hello there ");
}}
validationSchema={Yup.object().shape({
email: Yup.string()
.email()
.required("Required"),
password: Yup.string()
.required("No password provided.")
.min(8, "Password is too short - should be 8 chars minimum.")
.matches(/(?=.*[0-9])/, "Password must contain a number.")
})}>
{props => {
const {
values,
touched,
errors,
isSubmitting,
handleChange,
handleBlur,
handleSubmit
} = props;
return (
<div className="container">
<div className="row">
<form onSubmit={handleSubmit}>
<br />
<input
name="email"
type="text"
placeholder="Enter your email"
value={values.email}
onChange={handleChange}
onBlur={handleBlur}
className={errors.email && touched.email && "error"}
/>
<br />
<br />
{errors.email && touched.email && (
<div className="input-feedback">{errors.email}</div>
)}
<br />
<input
name="password"
type="password"
placeholder="Enter your password"
value={values.password}
onChange={handleChange}
onBlur={handleBlur}
className={errors.password && touched.password && "error"}
/> <br />
<br />
{errors.password && touched.password && (
<div className="input-feedback">{errors.password}</div>
)}
<button type="submit" disabled={isSubmitting}>
Login
</button>
</form>
</div>
<div className="row">
<button className="btn btn-default">Value</button>
</div>
</div>
);
}}
Maybe this will help you. Try to add function to onBlur prop then handle handleBlur function.
onBlur={(e) => {
handleBlur(e);
// here handle component showing
}}

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;
};

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

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

Resources