Submit button in react form not submitting - reactjs

I am trying to make a registration form using React.js and Formik. My submit button displays correctly but when I try to submit the information by clicking on the submit button nothing happens. Please advise how I can fix this. Thanks in advance.
RegistrationForm.js:
import React from 'react';
import { Formik, Form } from 'formik';
import * as yup from 'yup';
import FormikControl from './FormikControl';
import classes from './Registration.module.css';
function Registrationform() {
const options = [
{ key: 'Email', value: 'emailmoc' },
{ key: 'Telephone', vlaue: 'telephonemoc' }
];
const initialValues = {
email: '',
password: '',
confirmPassword: '',
modeOfContact: '',
phone: ''
};
const validationSchema = yup.object({
email: yup.string().email('Invalid email format').required('Required'),
password: yup.string().required('Required'),
confirmPassword: yup
.string()
.oneOf([yup.ref('password'), ''], 'Passwords must match')
.required('required'),
modeOfContact: yup.string().required('Required'),
phone: yup.string().when('modeOfContact', {
is: 'telephonemoc',
then: yup.string().required('Required')
})
});
const onSubmit = (values) => {
console.log('Form data', values);
};
return (
<div>
<h1>Registration</h1>
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={onSubmit}
>
{(formik) => {
return (
<Form className={classes.Registrationform}>
<FormikControl
control="input"
type="email"
label="Email"
name="email"
/>
<FormikControl
control="input"
type="password"
label="Password"
name="password"
/>
<FormikControl
control="input"
type="password"
label="Confirm Password"
name="confirmPassword"
/>
<FormikControl
control="input"
type="text"
label="Phone number"
name="phone"
/>
<label>Mode of Contact</label>
<div className="radio">
<label>
<input type="radio" value="Phone" options={options} />
Phone
</label>
</div>
<div className="radio">
<label>
<input type="radio" value="Email" options={options} />
Email
</label>
</div>
<button type="submit" disabled={!formik.isValid}>
Submit
</button>
</Form>
);
}}
</Formik>
</div>
);
}
export default Registrationform;
Registration.module.css:
.Registrationform{
margin:auto;
padding-top: 50px;
width:360px;
}
.Registrationform > label {
font-weight: bold;
display: flex;
margin-bottom: 10px;
font-size: 18px;
}
.Registrationform > input {
margin-bottom: 10px;
font-weight: bold;
display: inline-flex;
margin-right: 20px;
border-radius: 6px;
outline:none;
border: none;
border: 1px solid #1E90FF;
}
.Registrationform > button{
margin-top: 10px;
width: 425px;
height: 35px;
border-radius: 6px;
outline:none;
border: none;
border: 1px solid #1E90FF;
background-color: #1E90FF;
color: white;
font-size: 18px;
}
h1{
margin-top: 50px;
margin-bottom: 0;
padding-bottom: 0;
}
FormikContainer:
import React from 'react';
import { Formik, Form } from 'formik';
import * as Yup from 'yup';
import FormikControl from './FormikControl';
function FormikContainer() {
const initialValues = {
email: '',
password: ''
};
const validationschema = Yup.object({
email: Yup.string().required('Required')
});
const onSubmit = (values) => console.log('Form data', values);
return (
<div>
<Formik
initialValues={initialValues}
validationschema={validationschema}
onSubmit={onSubmit}
>
{(formik) => (
<Form>
<FormikControl
control="input"
type="email"
label="Email"
name="email"
/>
<FormikControl
control="input"
type="password"
label="Password"
name="password"
/>
<button type="submit">Submit</button>
</Form>
)}
</Formik>
</div>
);
}
export default FormikContainer;
FormikControl:
import React from 'react';
function FormikControl({ control, id, label, ...rest }) {
return (
<>
{control === 'input' && <label htmlFor={id}>{label}</label>}
<input id={id} {...rest} />
</>
);
}
export default FormikControl;
App.js:
import React from 'react';
import './App.css';
import FormikContainer from './components/FormikContainer';
import LoginForm from './components/LoginForm';
import Registrationform from './components/RegistrationForm';
function App() {
return (
<div>
<LoginForm />
<Registrationform />
</div>
);
}
export default App;

You need to bind the handleSubmit function of formik to Form onSubmit event listener.
add the onSubmit prop to the Form as below
<Form onSubmit={formik.handleSubmit}>
Or change your button code to (This approach is not mentioned in the formik doc)
<button disabled={!formik.isValid} onClick={formik.handleSubmit}>
Submit
</button>
Here is more on Form API and handleSubmit
Update
With respect to the #malik-hassam's answer:
You are missing the password field in validation schema.
const validationschema = Yup.object({
email: Yup.string().required('Required'),
password: Yup.string(),
});

There is missing password validation.
const LoginSchema = Yup.object().shape({
email: Yup.string()
.email("Email must be a valid email address")
.required("Email is required"),
password: Yup.string().required("Password is required"),
});
try use this.

Pls find your code working demo here link and same as you can do for login component
import React from "react";
import { Formik, Form } from "formik";
import * as Yup from "yup";
function Registrationform() {
const initialValues = {
email: "",
password: "",
confirmPassword: "",
modeOfContact: "email",
phone: ""
};
const validationSchema = Yup.object({
email: Yup.string().email("Invalid email format").required("Required"),
password: Yup.string().required("Password is required"),
confirmPassword: Yup.string().oneOf(
[Yup.ref("password"), null],
"Passwords must match"
),
modeOfContact: Yup.string().required("Required"),
phone: Yup.string().matches(/^[6-9]\d{9}$/, {
message: "Please enter valid number."
})
});
const onSubmit = (values) => {
console.log("Form data", values);
};
function FormikControl({ control, id, label, ...rest }) {
return (
<>
{control === "input" && <label htmlFor={id}>{label}</label>}
<input id={id} {...rest} />
</>
);
}
return (
<div>
<h1>Registration</h1>
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={onSubmit}
>
{({
handleChange,
errors,
touched,
handleBlur,
values,
isValid,
dirty
}) => (
<Form className="Registrationform">
<FormikControl
control="input"
type="email"
label="Email"
name="email"
onChange={handleChange}
onBlur={handleBlur}
value={values.email}
/>
{errors.email && touched.email && errors.email}
<FormikControl
control="input"
type="password"
label="Password"
name="password"
onChange={handleChange}
onBlur={handleBlur}
value={values.password}
/>
{errors.password && touched.password && errors.password}
<FormikControl
control="input"
type="password"
label="Confirm Password"
name="confirmPassword"
onChange={handleChange}
onBlur={handleBlur}
value={values.confirmPassword}
/>
{errors.confirmPassword &&
touched.confirmPassword &&
errors.confirmPassword}
<FormikControl
control="input"
type="text"
label="Phone number"
name="phone"
onChange={handleChange}
onBlur={handleBlur}
value={values.phone}
/>
{errors.phone && touched.phone && errors.phone}
<label>Mode of Contact</label>
<div className="custom-control">
<input
id="email"
type="radio"
value="email"
name="modeOfContact"
onChange={handleChange}
defaultChecked={values.modeOfContact === "email"}
/>
<label className="custom-control-label" htmlFor="email">
email
</label>
</div>
<div className="custom-control">
<input
id="phone"
type="radio"
value="phone"
name="modeOfContact"
onChange={handleChange}
defaultChecked={values.modeOfContact === "phone"}
/>
<label className="custom-control-label" htmlFor="phone">
phone
</label>
</div>
<button type="submit" disabled={!(isValid && dirty)}>
Submit
</button>
</Form>
)}
</Formik>
</div>
);
}
export default Registrationform;

Yes let me add an example of code. you can use this.
enter link description here
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;
}}
validationSchema={Yup.object().shape({
email: Yup.string()
.email()
.required("Email Required"),
password: Yup.string()
.required("Password Required")
.min(8, "Password is Too short")
.matches(/(?=.*[0-9])/, "Must Contain Number")
})}
>
{props => {
const {
values,
touched,
errors,
isSubmitting,
handleChange,
handleBlur,
handleSubmit
} = props;
return (
<>
<form onSubmit={handleSubmit}>
<label htmlFor="email">Email</label>
<input
name="email"
type="text"
placeholder="Enter your email"
value={values.email}
onChange={handleChange}
onBlur={handleBlur}
className={errors.email && touched.email && "error"}
/>
{errors.email && touched.email && (
<div className="input feedback">{errors.email}</div>
)}
<label htmlFor="email">Password</label>
<input
name="password"
type="password"
placeholder="Enter your password"
value={values.password}
onChange={handleChange}
onBlur={handleBlur}
className={errors.password && touched.password && "error"}
/>
{errors.password && touched.password && (
<div className="input feedback">{errors.password}</div>
)}
<button type="submit" disabled={isSubmitting}>
Login
</button>
</form>
</>
);
}}
</Formik>
</>
);
export default ValidatedLoginForm;

Related

React radio buttons not displaying in browser

I am new to React and formik and struggling to get my radio buttons to display in the browser. I think it is because the radio buttons are not defined as props in my formikcontrol function. How do I add it to the other props in my formikcontrol function? Please advise how to solve this issue. Thanks in advance
App.js:
import React from 'react';
import './App.css';
import FormikContainer from './components/FormikContainer';
import LoginForm from './components/LoginForm';
import Registrationform from './components/RegistrationForm';
function App() {
return (
<div>
<LoginForm />
<Registrationform />
</div>
);
}
export default App;
RegistrationForm:
import React from 'react';
import { Formik, Form } from 'formik';
import * as yup from 'yup';
import FormikControl from './FormikControl';
function Registrationform() {
const options = [
{ key: 'Email', value: 'emailmoc' },
{ key: 'Telephone', vlaue: 'telephonemoc' }
];
const initialValues = {
email: '',
password: '',
confirmPassword: '',
modeOfContact: '',
phone: ''
};
const validationSchema = yup.object({
email: yup.string().email('Invalid email format').required('Required'),
password: yup.string().required('Required'),
confirmPassword: yup
.string()
.oneOf([yup.ref('password'), ''], 'Passwords must match')
.required('required'),
modeOfContact: yup.string().required('Required'),
phone: yup.string().when('modeOfContact', {
is: 'telephonemoc',
then: yup.string().required('Required')
})
});
const onSubmit = (values) => {
console.log('Form data', values);
};
return (
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={onSubmit}
>
{(formik) => {
return (
<Form>
<FormikControl
control="input"
type="email"
label="Email"
name="email"
/>
<FormikControl
control="input"
type="password"
label="Password"
name="password"
/>
<FormikControl
control="input"
type="password"
label="Confirm Password"
name="confirmPassword"
/>
<FormikControl
control="radio"
type="Mode of contact"
label="modeOfContact"
options={options}
/>
<FormikControl
control="input"
type="text"
label="Phone number"
name="phone"
/>
<button type="submit" disabled={!formik.isValid}>
Submit
</button>
</Form>
);
}}
</Formik>
);
}
export default Registrationform;
FormikControl:
import React from 'react';
function FormikControl({ control, id, label, ...rest }) {
return (
<>
{control === 'input' && <label htmlFor={id}>{label}</label>}
<input id={id} {...rest} />
</>
);
}
export default FormikControl;
FormikContainer:
import React from 'react';
import { Formik, Form } from 'formik';
import * as Yup from 'yup';
import FormikControl from './FormikControl';
function FormikContainer() {
const initialValues = {
email: '',
password: ''
};
const validationschema = Yup.object({
email: Yup.string().required('Required')
});
const onSubmit = (values) => console.log('Form data', values);
return (
<div>
<Formik
initialValues={initialValues}
validationschema={validationschema}
onSubmit={onSubmit}
>
{(formik) => (
<Form>
<FormikControl
control="input"
type="email"
label="Email"
name="email"
/>
<FormikControl
control="input"
type="password"
label="Password"
name="password"
/>
<button type="submit">Submit</button>
</Form>
)}
</Formik>
</div>
);
}
export default FormikContainer;
In order to get radio button rendered using Formik, you have to import Field component and use it by sending type="radio", here is how it should look like:
enter link description here
Or by using the same component you created but with type="radio" :
<FormikControl
control="input"
type="radio"
.....
/>

How do I add a new row to table from Formik input values?

Here I am using flux pattern and Formik and yup to handle forms. How to implement onSubmit to add data?
import React from 'react'
import { useFormik } from 'formik'
import * as Yup from 'yup'
const CommentForm = () => {
const formik = useFormik({
initialValues: {
productname: '',
quantity: '',
price: '',
},
validationSchema: Yup.object({
productname: Yup.string()
.max(8, 'Must be 8 characters or less')
.required('Product Name is Required'),
quantity: Yup.string()
.min(1, 'Must be 1 character at a minimum')
.required('Quantity is Required'),
price: Yup.string()
.min(4, 'Must be enter 4 characters')
.required('Price is required'),
}),
/*onSubmit: values =>{
alert(JSON.stringify(values, null,2));
},*/
})
return (
<div>
<h1>ADD PRODUCT</h1>
<form onSubmit={formik.handleSubmit}>
<div>
<input
type="text"
name="productname"
placeholder="Enter Product Name"
onChange={formik.handleChange}
value={formik.values.productname}
/>
{formik.touched.productname && formik.errors.productname && (
<span style={{ color: 'red' }}>{formik.errors.productname}</span>
)}
</div>
<br />
<br />
<div>
<input
type="text"
name="quantity"
placeholder=" Enter Quantity"
onChange={formik.handleChange}
value={formik.values.quantity}
/>
{formik.touched.quantity && formik.errors.quantity && (
<span style={{ color: 'red' }}>{formik.errors.quantity}</span>
)}
</div>
<br />
<br />
<div>
<input
type="text"
name="price"
placeholder="Enter Price"
onChange={formik.handleChange}
value={formik.values.price}
/>
{formik.touched.price && formik.errors.price && (
<span style={{ color: 'red' }}>{formik.errors.price}</span>
)}
</div>
<br />
<button type="submit">Submit</button>
</form>
</div>
)
}
export default CommentForm

How to use useState hook in formik forms

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)

Submitting Formik form data to firebase database in react

I am trying to figure out how to send form data form a Formik form to a Firebase database in my react app.
I have a form as follows:
import React from 'react'
import { Link } from 'react-router-dom'
// import { Formik } from 'formik'
import { Formik, Form, Field, ErrorMessage, withFormik } from 'formik';
import * as Yup from 'yup';
import { Badge, Button, Col, Feedback, FormControl, FormGroup, FormLabel, InputGroup } from 'react-bootstrap';
import Select from 'react-select';
import firebase from '../../../firebase';
const style1 = {
width: '60%',
margin: 'auto'
}
const style2 = {
paddingTop: '2em',
}
const style3 = {
marginRight: '2em'
}
const style4 = {
display: 'inline-block'
}
const options = [
{ value: 'author', label: 'Author' },
{ value: 'reviewer', label: 'Reviewer' },
];
class Basic extends React.Component {
state = {
selectedOption: null,
}
handleChange = (selectedOption) => {
this.setState({ selectedOption });
console.log(`Option selected:`, selectedOption);
}
render() {
const { selectedOption } = this.state;
return (
<Formik
initialValues={{
firstName: '',
lastName: '',
email: '',
password: '',
confirmPassword: '',
selectedOption: null
}}
validationSchema={Yup.object().shape({
firstName: Yup.string()
.required('First Name is required'),
lastName: Yup.string()
.required('Last Name is required'),
email: Yup.string()
.email('Email is invalid')
.required('Email is required'),
selectedOption: Yup.string()
.required('It will help us get started if we know a little about your background'),
password: Yup.string()
.min(6, 'Password must be at least 6 characters')
.required('Password is required'),
confirmPassword: Yup.string()
.oneOf([Yup.ref('password'), null], 'Passwords must match')
.required('Confirm Password is required')
})}
// onSubmit={fields => {
// alert('SUCCESS!! :-)\n\n' + JSON.stringify(fields, null, 5))
// }}
// onSubmit={handleSubmit}
render={({ errors, status, touched }) => (
<Form style={style1}>
<h1 style={style2}>Get Started</h1>
<div className="form-group">
<label htmlFor="firstName">First Name</label>
<Field name="firstName" type="text" className={'form-control' + (errors.firstName && touched.firstName ? ' is-invalid' : '')} />
<ErrorMessage name="firstName" component="div" className="invalid-feedback" />
</div>
<div className="form-group">
<label htmlFor="lastName">Last Name</label>
<Field name="lastName" type="text" className={'form-control' + (errors.lastName && touched.lastName ? ' is-invalid' : '')} />
<ErrorMessage name="lastName" component="div" className="invalid-feedback" />
</div>
<div className="form-group">
<label htmlFor="email">Email</label>
<Field name="email" type="text" placeholder="Please use your work email address" className={'form-control' + (errors.email && touched.email ? ' is-invalid' : '')} />
<ErrorMessage name="email" component="div" className="invalid-feedback" />
</div>
<div className="form-group">
<label htmlFor="password">Password</label>
<Field name="password" type="password" className={'form-control' + (errors.password && touched.password ? ' is-invalid' : '')} />
<ErrorMessage name="password" component="div" className="invalid-feedback" />
</div>
<div className="form-group">
<label htmlFor="confirmPassword">Confirm Password</label>
<Field name="confirmPassword" type="password" className={'form-control' + (errors.confirmPassword && touched.confirmPassword ? ' is-invalid' : '')} />
<ErrorMessage name="confirmPassword" component="div" className="invalid-feedback" />
</div>
<div className="form-group">
<label htmlFor="selectedOption">Which role best describes yours?</label>
<Select
value={selectedOption}
onChange={this.handleChange}
options={options}
/>
</div>
<div className="form-group" >
<label htmlFor="consent">By registering you accept the <Link to={'/Terms'}>Terms of Use</Link> and <Link to={'/Privacy'}>Privacy Policy</Link> </label>
</div>
<div className="form-group">
<Button variant="outline-primary" type="submit" style={style3} id="submitRegistration">Register</Button>
</div>
</Form>
)}
/>
);
}
}
export default Basic;
I have a database in firebase (cloud firestore) with a collection called Registrations that has fields named the same as each of these form fields.
I have spent the day following tutorials that seem to be made for react before Formik. There's not much point to showing all the things I've tried and failed at for the day - they're clearly not written with Formik in mind. I can't find a way to write the onSubmit so that Formik can give the data to Firebase.
Has anyone found a current tutorial or know how to do this?
I've used Formik and Firebase in this Open-Source React project. Maybe this is what you're looking for :)
Expertizo React Native Kit

Is it possible to timeout and hide the error message of forms after some time in Formik?

How can I hide the error message of forms after some time in Formik (React form library).
Is there any method in Formik?
It shows Name is Required, Email is required, Message is required. But I want to hide it after sometime.
Here is my code :
import React from 'react';
import { withFormik, Form, Field } from 'formik';
import * as Yup from 'yup';
import './contact.scss';
const Contact = ({ errors, touched }) => {
return (
<section className="c-section c-contact u-padding-v-xlarge">
<h1>Get in touch</h1>
<p>We&apos;ll love to hear from you!</p>
<Form>
<div>
{touched.name && errors.name ? (
<p style={{ color: 'red' }}>{errors.name}</p>
) : null}
<Field
id="Name"
type="text"
name="name"
autoComplete="name"
placeholder="Your Name"
/>
</div>
<div>
{touched.email && errors.email ? (
<p style={{ color: 'red' }}>{errors.email}</p>
) : null}
<Field
id="message"
type="email"
name="email"
autoComplete="email"
placeholder="Your Email"
/>
</div>
<div>
{touched.message && errors.message ? (
<p style={{ color: 'red' }}>{errors.message}</p>
) : null}
<Field
component="textarea"
name="message"
id="message"
placeholder="Your Message"
/>
</div>
<button type="submit" className="button button--success button--block">
Send Message
</button>
</Form>
</section>
);
};
export default withFormik({
mapPropsToValues: () => ({
name: '',
email: '',
message: '',
}),
validationSchema: Yup.object().shape({
name: Yup.string().required('Name is required'),
email: Yup.string()
.email('Email not valid')
.required('Email is required'),
message: Yup.string().required('Message is required'),
}),
handleSubmit: (values, { resetForm }) => {
// Handle http request here
console.log(values);
setTimeout(resetForm(), 2000);
},
})(Contact);
I have tried setTimeout(resetForm(), 2000); passing resetForm but it doesn't work. Any alternative?
When you do setTimeout(resetForm(), 2000) you are not passing the function (you are calling it) to the setTimeout. You should do setTimeout(resetForm, 2000). If you want to reset errors you can use setErrors like in example https://codesandbox.io/s/941jzvx01p

Resources