How to prepopulate a react formik form - javascript

I have a table tha stores Students with an edit buttom tha opens a formik form.
const EditStudentFrom = (props) => (
<Formik
initialValues={{studentId:"", firstName: "", lastName: "", email: "", gender: "" }}
validate={(values) => {
const errors = {};
if (!values.firstName) {
errors.firstName = "First name required";
}
if (!values.lastName) {
errors.lastName = "Last name required";
}
if (!values.email) {
errors.email = " Email required";
} else if (
!/^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.email)
) {
errors.email = "Invalid Email address";
}
if (!values.gender) {
errors.gender = "Gender required";
} else if (
!["MALE ", "male", "female", "FEMALE"].includes(values.gender)
) {
errors.gender = "Gender most be ( MALE , male , FEMALE, female )";
}
return errors;
}}
onSubmit={(student, { setSubmitting }) => {
editStudent(student.studentId,student).then(() => {
props.onSuccess();
setSubmitting(false);
});
}}
>
{({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
isSubmitting,
submitForm,
isValid,
/* and other goodies */
}) => (
<form onSubmit={handleSubmit}>
<Input
style={inputMargin}
name="firstName"
onChange={handleChange}
onBlur={handleBlur}
value={values.firstName}
placeholder="First name"
/>
{errors.firstName && touched.firstName && (
<Tag style={tagStyle}>{errors.firstName}</Tag>
)}
<Input
style={inputMargin}
name="lastName"
onChange={handleChange}
onBlur={handleBlur}
value={values.lastName}
placeholder="Last name"
/>
{errors.lastName && touched.lastName && (
<Tag style={tagStyle}>{errors.lastName}</Tag>
)}
<Input
style={inputMargin}
type="email"
name="email"
onChange={handleChange}
onBlur={handleBlur}
value={values.email}
placeholder="Email"
/>
{errors.email && touched.email && (
<Tag style={tagStyle}>{errors.email}</Tag>
)}
<Input
style={inputMargin}
name="gender"
onChange={handleChange}
onBlur={handleBlur}
value={values.gender}
placeholder="Gender"
/>
{errors.gender && touched.gender && (
<Tag style={tagStyle}>{errors.gender}</Tag>
)}
<Button
onClick={() => submitForm()}
type="submit"
disabled={isSubmitting | (touched && !isValid)}
>
Submit
</Button>
</form>
)}
</Formik>
);
export default EditStudentFrom;
the eddit buttom on my table sets the visible property on a Modal to true to open the form
{
title:"",
Key:"buttom",
render:(value, student)=>(<Button onClick={this.openEditStudentModal}
>Edit</Button>)
}
how do i set the initialValues of the form to be the values for the student in the same row as the edit buttom i really need the studentId so i can pass it to the back end like this
export const editStudent= (studentId,student)=>
fetch(`http://localhost:1020/api/students/${studentId}`, {
method: "PUT",
body: JSON.stringify(student),
headers: {
"Content-Type": "application/json",
},
});

In order to use the form for editing the students objects, you need to pass the student object as initialValues of the <Formik>component. Note that you'll probably have to set the enableReinitialize prop to true, so Formik can reset the form when the initialValues prop changes.

Related

how to put API status json in the state?

I need to put the json in the register state to use it in different parts of the project
But unfortunately, after console.log(register); from that state, it returns an empty object in inspect
import React, { useEffect, useState } from "react";
import { Formik } from "formik";
// * icons
import { FaGoogle, FaFacebookF, FaGithub } from "react-icons/fa";
// *sweet alert
import swal from "sweetalert";
const Login = () => {
const [singUp, setSignUp] = useState(0);
const [register, setRegister] = useState();
useEffect(() => {
// console.log(register);
}, [singUp]);
return (
<div
className={
singUp > 0 ? "container py-5 right-panel-active" : "container py-5"
}
id="container"
>
<div className="form-container sing-up-container">
<Formik
initialValues={{
email: "",
password: "",
name: "",
invalidClass: "",
}}
validate={(values) => {
const errors = {};
if (!values.name) {
errors.name = "Required";
errors.invalidClass = "form-control is-invalid";
}
if (!values.email) {
errors.email = "Required";
errors.invalidClass = "is-invalid";
} else if (
!/^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.email)
) {
errors.email = "Invalid email address";
errors.invalidClass = "is-invalid";
}
if (!values.password) {
errors.password = "Required";
errors.invalidClass = "form-control is-invalid";
}
if (values.password.length < 8 && values.password.length > 0) {
errors.password = "is short";
errors.invalidClass = "form-control is-invalid";
}
if (values.password.length > 16) {
errors.password = "is Long";
errors.invalidClass = "form-control is-invalid";
}
return errors;
}}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
// !text message for status here
swal(
"Signed up!",
"Created account successfully! Please Login",
"success"
);
console.log(JSON.stringify(values, null, 2));
const data = {
name: values.name,
email: values.email,
password: values.password,
};
console.log(data);
console.log(values.name);
console.log(values.email);
console.log(values.password);
fetch("https://api.freerealapi.com/auth/register", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
name: data.name,
email: data.email,
password: data.password,
}),
})
// ! bug is here
.then((response) => response.json())
.then((json) => console.log(json))
.then((json) => setRegister(json));
// .then((response) =>
// setRegister({
// message: response.message,
// status: response.status,
// success: response.success,
// token: response.token,
// })
// );
// console.log(register);
console.log("hi");
setSubmitting(false);
}, 400);
}}
>
{({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
isSubmitting,
/* and other goodies */
}) => (
<form onSubmit={handleSubmit} className="py-3" action="">
<h1>Create Account</h1>
<div className="social-container">
<a href="" className="social">
<FaGoogle />
</a>
<a href="" className="social">
<FaFacebookF />
</a>
<a href="" className="social">
<FaGithub />
</a>
</div>
<span>Or use your email for Registration</span>
{/* // !name */}
<input
type="text"
name="name"
placeholder="Name"
className={
errors.name && touched.name && errors.name
? errors.invalidClass
: "form-control is-valid"
}
onChange={handleChange}
onBlur={handleBlur}
value={values.name}
/>
{errors.name && touched.name && errors.name}
{/* // !email */}
<input
type="email"
name="email"
placeholder="Email"
onChange={handleChange}
onBlur={handleBlur}
value={values.email}
className={
errors.email && touched.email && errors.email
? errors.invalidClass
: "form-control is-valid"
}
/>
{errors.email && touched.email && errors.email}
{/* // !password */}
<input
className={
errors.password && touched.password && errors.password
? errors.invalidClass
: "form-control is-valid"
}
placeholder="Password"
type="password"
name="password"
onChange={handleChange}
onBlur={handleBlur}
value={values.password}
/>
{errors.password && touched.password && errors.password}
<button type="submit" className="my-2" disabled={isSubmitting}>
Sing Up
</button>
</form>
)}
</Formik>
</div>
<div className="form-container sing-in-container">
<Formik
initialValues={{ email: "", password: "" }}
validate={(values) => {
const errors = {};
if (!values.email) {
errors.email = "Required";
errors.invalidClass = "is-invalid";
} else if (
!/^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.email)
) {
errors.email = "Invalid email address";
errors.invalidClass = "is-invalid";
}
if (!values.password) {
errors.password = "Required";
errors.invalidClass = "form-control is-invalid";
}
if (values.password.length < 8 && values.password.length > 0) {
errors.password = "is short";
errors.invalidClass = "form-control is-invalid";
}
if (values.password.length > 16) {
errors.password = "is Long";
errors.invalidClass = "form-control is-invalid";
}
return errors;
}}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
swal("Signed in!", "Login successfully! Please Wait", "success");
console.log(JSON.stringify(values, null, 2));
setSubmitting(false);
}, 400);
}}
>
{({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
isSubmitting,
/* and other goodies */
}) => (
<form action="" onSubmit={handleSubmit}>
<h1>Sign In</h1>
<div className="social-container">
<a href="" className="social">
<FaGoogle />
</a>
<a href="" className="social">
<FaFacebookF />
</a>
<a href="" className="social">
<FaGithub />
</a>
</div>
<span>or use your account</span>
<input
type="email"
name="email"
placeholder="Email"
onChange={handleChange}
onBlur={handleBlur}
value={values.email}
className={
errors.email && touched.email && errors.email
? errors.invalidClass
: "form-control is-valid"
}
/>
{errors.email && touched.email && errors.email}
<input
className={
errors.password && touched.password && errors.password
? errors.invalidClass
: "form-control is-valid"
}
placeholder="Password"
type="password"
name="password"
onChange={handleChange}
onBlur={handleBlur}
value={values.password}
/>
{errors.password && touched.password && errors.password}
<button className="my-2" type="submit" disabled={isSubmitting}>
Sing In
</button>
</form>
)}
</Formik>
</div>
<div className="overlay-container">
<div className="overlay">
<div className="overlay-panel overlay-left">
<h1>Welcome Back!</h1>
<p>
To keep connectied with up please login with your personal info
</p>
<button
className="devingine"
onClick={() => {
setSignUp(singUp - 1);
}}
id="signIn"
>
Sign In
</button>
</div>
<div className="overlay-panel overlay-right">
<h1>Hello, Friend!</h1>
<p>Enter your parsonal details and start journey with us.</p>
<button
className="devingine"
onClick={() => {
setSignUp(singUp + 1);
}}
id="signUp"
>
Sign Up
</button>
</div>
</div>
</div>
</div>
);
};
export default Login;
sorceCode
inspect is Here
The problem is in the second then statement in promises chain where console.log returns undefined value:
/* ... */
.then((response) => response.json())
.then((json) => console.log(json)) // <- console.log() returns undefined
.then((json) => setRegister(json));
/* ... */
When you chain promises you have to remember that value which is returned from promise is passed as and argument to callback of next promise in a chain.
You can do:
/* ... */
.then((response) => response.json())
.then((json) => {
console.log(json);
return json;
})
.then((json) => setRegister(json));
/* ... */

ReactJs with Bootstrap: Multistep form validation, using Formik and Yup

I'm developing a multistep form in ReactJs with Bootstrap, using Formik and Yup.
Actually, I have 2 problems here, despite I've read part of Formik and Yup documentation, I haven't found the answer yet.
I change my select fields' values, but the validationSchema simply ignores these values and only the initialValues are submitted to this validation.
Before validating my fields' values through validationSchema, I have to check whether the select option is not the first one (this first option is equivalent to "choose your option" for each field, and when the user submits it, it's value should be empty for the schema), it's possible to be done without validationSchema, by creating a validate function out of Formik, but I want to use Formik because I want a prettier way to display the errors as it does. I've tried plenty of stuff around, but I haven't gotten any answer until now.
Here is the Step 1 Form Code**
import React, { Component } from 'react';
import Form from 'react-bootstrap/Form';
import {ErrorMessage, Formik, validateYupSchema} from "formik";
import Col from 'react-bootstrap/Col';
import InputGroup from 'react-bootstrap/InputGroup';
import Button from 'react-bootstrap/Button';
import * as yup from 'yup';
import PropTypes from 'prop-types';
import {Categories} from './categoriesList.jsx';
import {Brands} from './brandsList';
import {ProductTypes} from './productTypesList';
import NewProduct from './newProductComponent.jsx';
let schema = yup.object().shape({
productCategory: yup.string().required(),
productBrand: yup.string().required(),
productType: yup.string().required()
});
class FormProducts1 extends Component {
reset = () => {
this.props.handleReset1();
}
render() {
const {values, handleChange, handleReset1} = this.props;
const CategoryOptions = Categories,
MakeItemCategory = function(itemCategory) {
return <option value={itemCategory} key={itemCategory}>{itemCategory}</option>;
};
const BrandOptions = Brands,
MakeItemBrand = function(itemBrand) {
return <option value={itemBrand} key={itemBrand}>{itemBrand}</option>;
};
const ProductOptions = ProductTypes,
MakeItemProduct = function(itemProduct) {
return <option value={itemProduct} key={itemProduct}>{itemProduct}</option>;
};
return (
<Formik
initialValues = {{
productCategory:'',
productBrand: '',
productType: ''
}}
validationSchema = {schema}
onSubmit = {
values => {console.log(values)}
}
>
{({
handleSubmit,
handleBlur,
touched,
isInvalid, //defines what is invalid
errors //catch up the errors to be displayed
}) => (
<Form onSubmit={handleSubmit}>
<Form.Group as={Col} md="12" controlId="formProduct.ProductCategory">
<Form.Label>Categoria do Produto</Form.Label>
<Form.Control
name="productCategory"
as="select"
onChange={handleChange('productCategory')}
value={values.productCategory}
onBlur={() => handleBlur('productCategory',true)}
isInvalid={touched.productCategory && errors.productCategory}
>
{CategoryOptions.map(MakeItemCategory)}
</Form.Control>
<Form.Control.Feedback type="invalid">{errors.productCategory}</Form.Control.Feedback>
</Form.Group>
<Form.Group as={Col} md="12" controlId="formProduct.ProductBrand">
<Form.Label>Marca do Produto</Form.Label>
<Form.Control
name="productBrand"
as="select"
onChange={handleChange('productBrand')}
value={values.productBrand}
onBlur = {() => handleBlur('productBrand',true)}
isInvalid = {touched.productBrand && errors.productBrand} >
{BrandOptions.map(MakeItemBrand)}
</Form.Control>
<Form.Control.Feedback type="invalid">{errors.productBrand}</Form.Control.Feedback>
</Form.Group>
<Form.Group as={Col} md="12" controlId="formProduct.ProductType">
<Form.Label>Tipo do Produto</Form.Label>
<Form.Control
name="productType"
as="select"
onChange={handleChange('productType')}
value={values.productType}
onBlur = {() => handleBlur('productType',true)}
isInvalid={touched.productType && errors.productType}>
{ProductOptions.map(MakeItemProduct)}
</Form.Control>
<Form.Control.Feedback type="invalid">{errors.productType}</Form.Control.Feedback>
</Form.Group>
<Form.Group controlId="buttonsCategory" style={this.formatForm}>
<Button variant="secondary m-2" type="reset" style={this.styleAddButton} onClick={this.reset}>
Limpar
</Button>
<Button variant="primary" type="submit" style={this.styleAddButton}>
Continuar
</Button>
</Form.Group>
</Form>
)}
</Formik>
);
}
}
export default FormProducts1;
*****************Here is the Steps' Container Component Code *******************
import React, { Component } from 'react';
import FormProducts1 from './formProducts1';
import FormProducts2 from './formProducts2';
import FormProducts3 from './formProducts3';
import FormProductsSuccess from './formProductsSuccess';
import PropTypes from "prop-types";
class NewProduct extends Component {
state = {
step:1,
productCategory:'',
productBrand:'',
productType:'',
productName:'',
productPrice:0,
productCode:'',
productDescription:''
}
formatForm = {
marginTop:15
};
styleAddButton = {
fontSize:15,
fontWeight:"bold"
};
//Proceed to the next step
nextStep = () => {
const {step} = this.state
this.setState({
step: step + 1
});
}
//Go back to previous step <div>
prevStep = () => {
const {step} = this.state
this.setState({
step: step - 1
});
}
//Handle fields change
handleChange = input => e => {
this.setState({
[input]: e.target.value
});
}
toCurrency(number) {
const formatter = new Intl.NumberFormat("pt-BR", {
style: "decimal",
currency: "BRL"
});
return formatter.format(number);
}
handleReset1 = () => {
this.setState({
productCategory:'',
productBrand:'',
productType:''
});
}
handleReset2 = () => {
this.setState({
productName:'',
productPrice:0,
productCode:'',
productDescription:''
});
}
render() {
const {step} = this.state;
const {productCategory, productBrand, productType, productName, productPrice, productCode, productDescription} = this.state;
const values = {productCategory, productBrand, productType, productName, productPrice, productCode, productDescription};
switch(step){
case 1:
return (
<FormProducts1 nextStep = {this.nextStep}
handleChange = {this.handleChange} handleReset1 = {this.handleReset1}
values={values}
/>
)
case 2:
return(
<FormProducts2 nextStep = {this.nextStep}
prevStep = {this.prevStep} handleChange = {this.handleChange}
handleReset2 = {this.handleReset2}
values={values} toCurrency = {this.toCurrency}
/>
)
case 3:
return(
<FormProducts3 nextStep = {this.nextStep} prevStep = {this.prevStep}
values={values} toCurrency = {this.toCurrency}
/>
)
case 4:
return(
<FormProductsSuccess/>
)
}
}
}
NewProduct.propTypes = {
value: PropTypes.string,
onChange: PropTypes.func
};
export default NewProduct;
Thanks!
It took two days to make it error-free... and I had hoped this would be work at your end..
Here, you can find react-bootstrap all input(form-control) along with formik and yup validation package
import React from 'react';
import { Container, Row, Col, Image, Form, Button } from 'react-bootstrap';
import style from '../styles/Contact.module.css';
import { Formik, Field} from 'formik';
import * as Yup from 'yup';
const dropdown=[
{
key:"Select an option",
value:""
},
{
key:"Option 1",
value:"option1"
},
{
key:"Option 2",
value:"option2"
},
{
key:"Option 3",
value:"option3"
}
]
// RegEx for phone number validation
const phoneRegExp = /^(\+?\d{0,4})?\s?-?\s?(\(?\d{3}\)?)\s?-?\s?(\(?\d{3}\)?)\s?-?\s?(\(?\d{4}\)?)?$/
// Schema for yup
const validationSchema = Yup.object().shape({
name: Yup.string()
.min(2, "*Names must have at least 2 characters")
.max(30, "*Names can't be longer than 30 characters")
.required("*Name is required"),
email: Yup.string()
.email("*Must be a valid email address")
.max(100, "*Email must be less than 100 characters")
.required("*Email is required"),
phone: Yup.string()
.min(10, "*Names can't be longer than 10 numbers")
.matches(phoneRegExp, "*Phone number is not valid")
.required("*Phone number required"),
msg: Yup.string()
.min(2, "*Messages must have at least 2 characters")
.max(250, "*Messages can't be longer than 250 characters")
.required("*Messages is required"),
selectionOption: Yup.string()
// .of(Yup.string())
// .min(1)
.required('Required'),
});
const Signup = () => {
return (
<>
<Formik
initialValues={{ name: "", email: "", phone: "", msg: "",selectionOption:"" }}
validationSchema={validationSchema}
onSubmit={(values, { setSubmitting, resetForm }) => {
// When button submits form and form is in the process of submitting, submit button is disabled
console.log(values)
setSubmitting(true);
// Simulate submitting to database, shows us values submitted, resets form
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
resetForm();
setSubmitting(false);
}, 500);
}}
>
{({ values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
isSubmitting }) => (
<Form className="form" onSubmit={handleSubmit} autoComplete="off" name="contact" method="POST" >
<Row className="mb-5">
<Col lg={6} md={6} sm={12}>
<Form.Group controlId="formName">
<Form.Label className="form_label" >FullName</Form.Label>
<Form.Control
type="text"
name="name"
placeholder="Full Name"
onChange={handleChange}
onBlur={handleBlur}
value={values.name}
className={touched.name && errors.name ? "has-error" : null}
/>
{touched.name && errors.name ? (
<div className="error-message">{errors.name}</div>
) : null}
</Form.Group>
</Col>
<Col lg={6} md={6} sm={12}>
<Form.Group>
<Form.Label className="form_label" >Number</Form.Label>
<Form.Control
type="text"
name="phone"
placeholder="Phone"
onChange={handleChange}
onBlur={handleBlur}
value={values.phone}
className={touched.phone && errors.phone ? "has-error" : null}
/>
{touched.phone && errors.phone ? (
<div className="error-message">{errors.phone}</div>
) : null}
</Form.Group>
</Col>
</Row>
<Row className="mb-5">
<Col lg={6} md={6} sm={12}>
<Form.Group>
<Form.Label className="form_label" >Email</Form.Label>
<Form.Control
type="text"
name="email"
placeholder="Email"
onChange={handleChange}
onBlur={handleBlur}
value={values.email}
className={touched.email && errors.email ? "has-error" : null}
/>
{touched.email && errors.email ? (
<div className="error-message">{errors.email}</div>
) : null}
</Form.Group>
</Col>
<Col lg={6} md={6} sm={12}>
{/* <Form.Select aria-label="Default select example">
<option>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</Form.Select> */}
<Form.Group controlId="exampleForm.ControlSelect1">
<Form.Label>Example select</Form.Label>
<Form.Control as="select" name ="selectionOption" onChange={handleChange}
onBlur={handleBlur} value={values.selectionOption}
className={touched.selectionOption && errors.selectionOption ? "has-error" : null}
>
{
dropdown.map(drop=>{return(
<option key={drop.value} value={drop.value}>
{drop.key}
</option>
)
}
)
}
</Form.Control>
{/* <ErrorMessage name="selectionOption"></ErrorMessage> */}
{touched.selectionOption && errors.selectionOption ? (
<div className="error-message">{errors.selectionOption}</div>
) : null}
{/* <Form.Label>Example select</Form.Label>
<Field as="select" name ="selectionOption" onChange={handleChange}
onBlur={handleBlur} value={values.selectionOption}
style={{ display: "block" }}
// isValid={touched.selectionOption && !errors.selectionOption}
// isInvalid={!errors.selectionOption}
className={touched.selectionOption && errors.selectionOption ? "has-error" : null}
>
<option className='text-muted'>---</option>
<option value="ortho">ortho</option>
<option value="pedri">pedri</option>
<option value="crown">crown</option>
</Field>
{touched.selectionOption && errors.selectionOption ? (
<div className="error-message">{errors.selectionOption}</div>
) : null} */}
</Form.Group>
</Col>
</Row>
<Row className="mb-5">
<Col lg={12} md={12} sm={12}>
<Form.Group controlId="formmsg">
<Form.Label>Messages :</Form.Label>
<Form.Control
type="text"
name="msg"
as="textarea" rows={4}
placeholder="Query / Feedback"
onChange={handleChange}
onBlur={handleBlur}
value={values.msg}
className={touched.msg && errors.msg ? "has-error" : null}
/>
{touched.msg && errors.msg ? (
<div className="error-message">{errors.msg}</div>
) : null}
</Form.Group>
</Col>
</Row>
<Button type="submit" className={style.customizeBtn} name="contact" id="contact" disabled={isSubmitting}>
<Image src="img/send.png" className={style.imgBtn} />
<span className={style.titleBtn}>Submit</span>
</Button>
</Form>
)}
</Formik>
</>
)
}
export default Signup;

Check user name availability from firebase in react

I am currently stuck on checking unique username in the sign up(on firebase) in react. My goal is that
1. when the user input the username, the function checkNameAvalaible go to the firebase database and check if the name exists.
2.if the name exists set the state of usernameavalaible to false, and set it to true if name works
3.disable the submit button of the sign up if the usernameavalaible is false.
4.If the username is taken, use helper text in textfield to alert the current user.
I am stuck with the if statement, I tried a few times and it is not working here is my code
import React, { Component } from "react";
import { Link } from "react-router-dom";
import { auth } from "../firebase";
import { db} from "../firebase";
import "./auth.css";
import * as routes from "../constants/routes";
import { SignInLink } from "./SignIn";
import TextField from "#material-ui/core/TextField";
import Button from "#material-ui/core/Button";
const SignUpPage = ({ history }) => (
<div align="center" className="SignUpBox">
<h1>SignUp</h1>
<SignUpForm history={history} />
<SignInLink />
</div>
);
const INITIAL_STATE = {
username: "",
name: "",
email: "",
passwordOne: "",
passwordTwo: "",
error: null
};
const byPropKey = (propertyName, value) => () => ({
[propertyName]: value
});
class SignUpForm extends Component {
state = { ...INITIAL_STATE };
// checkPassword() {
// if(!this.state.passwordOne || this.state.passwordOne !== this.state.passwordTwo){
// this.setState({error:"passwords do not match"});
// }
// else {
// this.setState({error:null});
// }
// }
onSubmit = event => {
event.preventDefault();
const { email, passwordOne, name, username } = this.state;
auth
.doCreateUserWithEmailAndPassword(
email,
passwordOne,
name,
username
)
.then(authUser => {
this.setState(() => ({ ...INITIAL_STATE }));
this.props.history.push(routes.HOME);
})
.catch(error => {
this.setState(byPropKey("error", error));
});
};
render() {
var usernameAvalaible
const {
username,
name,
email,
passwordOne,
passwordTwo,
error
} = this.state;
checkNameAvalaible(){
if (db.doc(`/users/${username}`).get().exists){
this.setState{usernameAvalaible:false};
}
else{
this.setState{usernameAvalaible:true};
}
};
const isInvalid =
passwordOne !== passwordTwo ||
passwordOne === "" ||
email === "" ||
name === "" ||
username === ""|| usernameAvalaible===false;
return (
<form onSubmit={this.onSubmit}>
<TextField
name="Username"
id="standard-secondary"
label="User name"
color="primary"
value={username}
onChange={event =>
this.setState(byPropKey("username", event.target.value))
}
type="text"
/>
<TextField
name="name"
value={name}
id="standard-secondary"
label="Full name"
color="primary"
onChange={event =>
this.setState(byPropKey("name", event.target.value))
}
type="text"
/>
<TextField
name="email"
value={email}
id="standard-secondary"
label="Email Address"
color="primary"
onChange={event =>
this.setState(byPropKey("email", event.target.value))
}
type="email"
/>
<TextField
name="password"
value={passwordOne}
id="standard-secondary"
label="Password"
color="primary"
onChange={event =>
this.setState(byPropKey("passwordOne", event.target.value))
}
type="password"
/>
<TextField
name="ConfirmPassword"
value={passwordTwo}
id="standard-secondary"
label="Comfirm Password"
color="primary"
onChange={event =>
this.setState(byPropKey("passwordTwo", event.target.value))
}
type="password"
/>
<br />
<br />
<Button
type="submit"
disabled={isInvalid}
variant="contained"
color="primary"
>
Sign Up
</Button>
{error && <p style={{ color: "red" }}>{error.message}</p>}
</form>
);
}
}
const SignUpLink = () => (
<p>
Don't have an account? <Link to={routes.SIGN_UP}>Sign Up</Link>
</p>
);
export default SignUpPage;
export { SignUpForm, SignUpLink };

Mapping Elements in a Form (for Formik)

In my form, I am using Formik/Yup for Validation. Currently, this works in my form perfectly:
export default function AddUserPage() {
const [firstName, setFirstName] = useState("");
const [email, setEmail] = useState("");
return (
<div>
<Formik
initialValues={{ firstName: "", email: "" }}
onSubmit={(values, actions) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
actions.setSubmitting(false);
}, 1000);
}}
validationSchema={schema}
>
{props => {
const {
values: { firstName, lastName, email, password, phone },
errors,
touched,
handleChange,
isValid,
setFieldTouched
} = props;
const change = (name: string, e: any) => {
e.persist();
handleChange(e);
setFieldTouched(name, true, false);
};
return (
<div className="main-content">
<form style={{ width: "100%" }}>
<div>
<TextField
variant="outlined"
margin="normal"
id="firstName"
name="firstName"
helperText={touched.firstName ? errors.firstName : ""}
error={touched.firstName && Boolean(errors.firstName)}
label="First Name"
//onChange={e => setFirstName(e.target.value)}
value={firstName}
onChange={change.bind(null, "firstName")}
/>
<br></br>
<TextField
variant="outlined"
margin="normal"
id="email"
name="email"
helperText={touched.email ? errors.email : ""}
error={touched.email && Boolean(errors.email)}
label="Email"
value={email}
onChange={change.bind(null, "email")}
/>
<br></br>
</div>
</form>
</div>
);
}}
</Formik>
</div>
);
}
However, instead of typing everything, I want to map my text fields. How could I map my text fields?
I tried something like this but I get errors for helperText and error properties:
{[{ label: "First Name", state: firstName , type: "text", function: setFirstName},
{ label: "Email", state: email , type: "text", function: setEmail},
]}.map((item, index) => (
<div>
<TextField
id="outlined-basic"
key={index}
label={item.label}
variant="outlined"
type= {item.type}
helperText= {touched[item.state] ? errors[item.state] : ""}
onChange={change.bind(null, state)}
/>
<br></br><br></br>
</div>
)
Here, I get an error on helper text that:
Element implicitly has an 'any' type because expression of type 'any' can't be used to index type 'FormikTouched<{ firstName: string; lastName: string; email: string; password: string; phone: string; }>'
I tried adding this as well but this also gives me an error:
helperText = {touched.item.state}
Looks like you have an synthetic error figure bracket before .map
this code render some jsx with map:
[
{ label: "First Name", type: "text"},
{ label: "Email", type: "text"},
].map((item, i) => (
<div>
<TextField
key={i}
label={item.label}
type= {item.type}
/>
</div>
)

Why isn't Formik.setStatus updating the Status state in my form?

I'm using Formik to create a generic contact form in react. I am getting data from my api and attempting to call Formik's setStatus to generate a message to show that the form has been submitted successfully.
For whatever reason the Status state never gets updated to reflect what I put in setStatus.
Here's my code:
import { Formik, Form, useField } from "formik";
import * as Yup from "yup";
import axios from "axios";
import Button from "components/shared/button";
import "styles/contact/form.scss";
const handleSubmit = (values, actions) => {
axios.post("http://localhost:5000/sendemail/", values).then(res => {
actions.setSubmitting(false);
actions.setStatus = {
message: res.data.message
};
setTimeout(() => {
actions.resetForm();
}, 3000);
});
};
const FormField = ({ label, tagName, ...props }) => {
const [field, meta] = useField(props);
const errorClass = meta.touched && meta.error ? "error" : "";
const TagName = tagName;
return (
<>
<label htmlFor={props.id || props.name}>
{label}
{meta.touched && meta.error ? (
<span className="error">{meta.error}</span>
) : null}
</label>
<TagName
className={`form-control ${errorClass}`}
{...field}
{...props}
/>
</>
);
};
const ContactForm = () => (
<Formik
initialValues={{ name: "", email: "", msg: "" }}
validationSchema={Yup.object({
name: Yup.string().required("Required"),
email: Yup.string()
.email("Invalid email address")
.required("Required"),
msg: Yup.string().required("Required")
})}
onSubmit={handleSubmit}>
{({ isSubmitting, status }) => (
<Form className="contact-form">
<div className="row form-group">
<div className="col">
<FormField
label="Name"
name="name"
type="text"
tagName="input"
/>
</div>
<div className="col">
<FormField
label="Email"
name="email"
type="text"
tagName="input"
/>
</div>
</div>
<div className="form-group">
<FormField label="Message" name="msg" tagName="textarea" />
</div>
{status && status.message && (
<div className="message">{status.message}</div>
)}
<Button
id="formSubmit"
text="Send Message"
type="submit"
isSubmitting={isSubmitting}
/>
</Form>
)}
</Formik>
);
export default ContactForm;
Just before my submit button, it should show the <div class="message">Success message</div> after submitting the form. When I try to debug the value of Status is always "undefined".
Any one have a clue what I'm doing wrong here?
The reason it wasn't working is because I tried to set the value of setStatus equal to an object. What I should have done was used it as a method and pass the object as a parameter.
Like so:
actions.setStatus({message: res.data.message});
I feel silly for missing this simple mistake for so long.

Categories

Resources