1st component (here is the modal)
import './Register.css';
import {useFormik} from 'formik';
import * as Yup from 'yup';
import {useNavigate} from 'react-router-dom';
import {registerUser} from '../../services/auth.service';
import {
createUser,
getUserByUsername,
} from '../../services/user.request.services.js';
import {useContext} from 'react';
import AppContext from '../../context/AppContext.js';
export default function Register() {
const navigate = useNavigate();
const {addToast} = useContext(AppContext);
const formik = useFormik({
initialValues: {
username: '',
firstName: '',
lastName: '',
email: '',
password: '',
},
validationSchema: Yup.object({
username: Yup.string()
.max(50, 'Username must be maximum 50 symbols')
.required('Please, choose username.')
.min(4, 'username must be minimum 4 symbols'),
firstName: Yup.string()
.max(32, 'Last name must be maximum 32 symbols')
.min(4, 'First name must be minimum 4 symbols')
.required('You need to apply first name!'),
lastName: Yup.string()
.max(32, 'First name must be maximum 32 symbols')
.min(4, 'Last name must be minimum 4 symbols')
.required('You need to apply last name!'),
email: Yup.string()
.email('Must be a valid email address')
.required('Email is required!'),
password: Yup.string().required('Please, type your password.'),
}),
onSubmit: async (values) => {
try {
const user = await getUserByUsername(values.username);
if (user !== null) {
formik.errors.username = 'Username already in use!';
return;
}
const credentials = await registerUser(values.email, values.password);
try {
await createUser(
values.firstName,
values.lastName,
values.email,
values.username,
credentials.user.uid,
);
} catch (error) {
addToast('error', 'Something went wrong!');
}
} catch (error) {
if (error.message.includes('auth/email-already-in-use')) {
formik.errors.email = 'This email is already in use!';
return;
}
addToast('error', 'Something went wrong');
}
addToast('success', 'You have been registered!');
addToast('success', 'Welcome to the UnHOOman Forum!');
navigate('/');
},
});
const resetFormHandler = () => {
formik.resetForm();
};
return (
<>
<label htmlFor="register-modal">
<p className="cursor-pointer">Register</p>
</label>
<input type="checkbox" id="register-modal" className="modal-toggle" />
<div className="modal modal-bottom sm:modal-middle">
<div className="modal-box min-h-1/2">
<div className="modal-action m-0 justify-center gap-2 h-full border-2 border-[#F79E47]">
<form onSubmit={formik.handleSubmit} className="w-full">
<div className='form-wrapper'>
<h1 className="font-bold">Register</h1>
<input
type="text"
placeholder="Username..."
name="username"
value={formik.values.username}
onBlur={formik.handleBlur}
onChange={formik.handleChange}
className="input w-full input-bordered border-[#F79E47] max-w-xs block"
/>
{formik.touched.username && formik.errors.username ? (
<p className="text-red-700 text-sm">{formik.errors.username}</p>
) : null}
<input
type="text"
placeholder="First name..."
name="firstName"
value={formik.values.firstName}
onBlur={formik.handleBlur}
onChange={formik.handleChange}
className="input input-bordered border-[#F79E47] w-full max-w-xs"
/>
{formik.touched.firstName && formik.errors.firstName ? (
<p className="text-red-700 text-sm">{formik.errors.firstName}</p>
) : null}
<input
type="text"
placeholder="Last name..."
name="lastName"
value={formik.values.lastName}
onBlur={formik.handleBlur}
onChange={formik.handleChange}
className="input input-bordered border-[#F79E47] w-full max-w-xs"
/>
{formik.touched.lastName && formik.errors.lastName ? (
<p className="text-red-700 text-sm">{formik.errors.lastName}</p>
) : null}
<input
type="email"
placeholder="Email..."
name="email"
value={formik.values.email}
onBlur={formik.handleBlur}
onChange={formik.handleChange}
className="input input-bordered border-[#F79E47] w-full max-w-xs"
/>
{formik.touched.email && formik.errors.email ? (
<p className="text-red-700 text-sm">{formik.errors.email}</p>
) : null}
<input
type="password"
placeholder="Password..."
name="password"
value={formik.values.password}
onBlur={formik.handleBlur}
onChange={formik.handleChange}
className="input input-bordered border-[#F79E47] w-full max-w-xs"
/>
{formik.touched.password && formik.errors.password ? (
<p className="text-red-700 text-sm">{formik.errors.password}</p>
) : null}
<div className="signup-buttons">
<label
type="button"
htmlFor="register-modal"
className="btn btn-outline"
onClick={() => resetFormHandler()}
>
CANCEL
</label>
<button type="submit" className="btn btn-outline">
Submit
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</>
);
}
2nd component from which I want to be able to trigger the modal
import {HOME_CARD_TITLE, HOME_CARD_DESC} from '../../common/constants.js';
import {useContext, useEffect, useState} from 'react';
import {getAllPosts} from '../../services/posts.service.js';
import {getAllUsers} from '../../services/user.request.services.js';
import AppContext from '../../context/AppContext.js';
import {Navigate, useNavigate} from 'react-router-dom';
export default function HomeInfoCard() {
const [cardState, setCardState] = useState({posts: 0, members: 0});
const {addToast} = useContext(AppContext);
const navigate = useNavigate();
useEffect(() => {
const updatePostsAndUsers = async () => {
const posts = (await getAllPosts()).length;
const members = (await getAllUsers()).length;
setCardState((prev) => ({
...prev,
posts,
members,
}));
};
updatePostsAndUsers().catch((error) => addToast('error', error.message));
}, []);
return (
<div className="card max-w-md bg-base-100 shadow-xl">
<div className="card-body">
<h2 className="card-title">{ HOME_CARD_TITLE }</h2>
<p className="mb-3">{ HOME_CARD_DESC }</p>
<div className="stats shadow text-center mb-3">
<div className="stat">
<div className="stat-title">Posts</div>
<div className="stat-value">{ cardState.posts }</div>
</div>
<div className="stat">
<div className="stat-title">Members</div>
<div className="stat-value">{ cardState.members }</div>
</div>
</div>
<div className="card-actions justify-center">
<button className="btn bg-[#FCDDBF] border-0 text-[#4A4846] hover:text-[#fff] w-full" onClick={() => navigate('/login')}>Join community</button>
</div>
</div>
</div>
);
}
I have two components, the first one is a register form with Formik and there is also a modal from daisyUI.
I have a 'View community button' in other component which I want to be able to make on click to open the register form modal from the other component, but I couldn't find a solution for this problem.
I've tried with data-toggle/data-target, but it didn't work.
The button which I want to be able to trigger the modal from the register component is in the end of the second component and it's currently leading to the home page with useNavigate.
I am not a professional programmer, and currently I am in a boot camp, so that's why the code is trashy, but we all start from somewhere. Thanks in advance for the replies!
Related
Hi guys i want to pass 'error' coming from nodejs backend to onsubmit the problem that even if the error passes i still navigate to login page
this is my code :
import "./form_inscription.css";
import { useState } from "react";
import { useFormik } from "formik";
import { validationSchemaBase } from "./formsScema";
//reactstrap componenets
import { FormGroup, Label, Input, Alert } from "reactstrap";
//icons and assets
import ArrowLeft from "../../../../assets/icons/Arrow-Left.png";
import { useDispatch, useSelector } from "react-redux";
// import { registerUser } from "../../../../store/features/authentication/inscription/inscriptionThunk";
import { registerUser } from "../../../../store/features/authentication/authentificationThunk";
import { useNavigate } from "react-router-dom";
import { Eye, EyeOff } from "react-feather";
import { useEffect } from "react";
const FormIscriptionEtape1 = () => {
const [checkboxError, setCheckboxError] = useState(false);
const [showPassword, setShowPassword] = useState(false);
const { error } = useSelector((store) => store.authentification);
const onSubmit = (values) => {
if (values.password === values.passConfirm) {
//checkbox error handling conditions
if (values.cPartner || values.aPartner || values.sPartner) {
setCheckboxError(false);
dispatch(registerUser(values));
if (!error) {
navigate("/login");
}
} else {
setCheckboxError(true);
}
//catch error handling
} else {
console.log("mot de passe non conforme!!");
}
};
const togglePasswordVisibility = () => {
setShowPassword((prevState) => !prevState);
};
const dispatch = useDispatch();
//formik data management
const {
values,
handleChange,
handleBlur,
handleSubmit,
setFieldValue,
errors,
touched,
} = useFormik({
initialValues: {
email: "",
password: "",
passConfirm: "",
cPartner: false,
aPartner: false,
sPartner: false,
},
validationSchema: validationSchemaBase.test(
"one check-box-required",
"Veuillez sélectionner le type de votre organsime",
(values) => values.aPartner || values.sPartner || values.cPartner
),
onSubmit,
});
//handle check boxes
const handleChangeBox = (event) => {
const { name, value, checked } = event.target;
if (name === "cPartner" || name === "aPartner" || name === "sPartner") {
setFieldValue(name, checked);
if (name === "cPartner") {
setFieldValue("aPartner", false);
setFieldValue("sPartner", false);
setCheckboxError(false);
} else if (name === "aPartner") {
setFieldValue("cPartner", false);
setFieldValue("sPartner", false);
setCheckboxError(false);
} else {
setFieldValue("cPartner", false);
setFieldValue("aPartner", false);
setCheckboxError(false);
}
} else {
setFieldValue(name, value);
setCheckboxError(false);
}
};
//navigation to Login screen through the back button temporary will be deleted in the future
const navigate = useNavigate();
const handleNavigateLogin = () => {
navigate("/login");
};
return (
<div>
<div className="w-100 d-flex flex-column justify-content-center align-items-center">
<div className="w-50 mb-1">
<FormGroup className="mt-2">
<Label
className="label_title_inscription text_600_nrm"
for="exampleEmail"
>
Email
</Label>
<Input
className="input_text_off"
type="email"
name="email"
value={values.email}
onChange={handleChange}
onBlur={handleBlur}
/>
{errors.email && (
<p className="validation_problems">{errors.email}</p>
)}
</FormGroup>
</div>
<div className="w-50 mb-1">
<div className=" justify-content-between">
<FormGroup className="auth-login-form mt-2">
<Label
className="label_title_inscription text_600_nrm"
for="examplePassword"
>
Mot de passe
</Label>
<Input
className="input_text_off"
type={showPassword ? "text" : "password"}
name="password"
value={values.password}
onChange={handleChange}
onBlur={handleBlur}
/>
{/* <div
className="password-visibility-icon"
onClick={togglePasswordVisibility}
>
{showPassword ? <Eye size={20} /> : <EyeOff size={20} />}
</div> */}
{errors.password && touched.password && (
<p className="validation_problems">{errors.password}</p>
)}
</FormGroup>
</div>
</div>
<div className="w-50 mb-1">
<div className=" justify-content-between">
<FormGroup className="auth-login-form mt-2">
<Label
className="label_title_inscription text_600_nrm"
for="examplePassword"
>
Confirmation mot de passe
</Label>
<Input
className="input_text_off"
type={showPassword ? "text" : "password"}
name="passConfirm"
value={values.passConfirm}
onChange={handleChange}
onBlur={handleBlur}
/>
{/* <div
className="password-visibility-icon"
onClick={togglePasswordVisibility}
>
{showPassword ? <Eye size={20} /> : <EyeOff size={20} />}
</div> */}
{errors.passConfirm && touched.passConfirm && (
<p className="validation_problems">{errors.passConfirm}</p>
)}
</FormGroup>
</div>
</div>
</div>
{/* checkbox section */}
<p className="text-center mt-5 checkbox_text_inscription text_600_nrm">
Vous êtes
</p>
{checkboxError && (
<p className="validation_problems error_validation_check">
Veuillez sélectionner le type de votre organsime
</p>
)}
<div className="d-flex justify-content-center checkbox">
<div className="form-check d-flex checks_gap">
<Input
type="checkbox"
className="form-check"
name="cPartner"
checked={values.cPartner}
onChange={handleChangeBox}
/>
<Label
className="form-check-Label checkbox_text_inscription text_600_nrm"
htmlFor="formrow-customCheck"
>
Commercial
</Label>
</div>
<div className="form-check d-flex checks_gap">
<Input
type="checkbox"
className="form-check"
name="sPartner"
checked={values.sPartner}
onChange={handleChangeBox}
/>
<Label
className="form-check-Label checkbox_text_inscription text_600_nrm"
htmlFor="formrow-customCheck"
>
Educatif
</Label>
</div>
<div className="form-check d-flex checks_gap">
<Input
type="checkbox"
className="form-check"
name="aPartner"
checked={values.aPartner}
onChange={handleChangeBox}
/>
<Label
className="form-check-Label checkbox_text_inscription text_600_nrm"
htmlFor="formrow-customCheck"
>
Associatif
</Label>
</div>
</div>
{error ? <Alert color="danger">{error.message}</Alert> : null}{" "}
<div className="w-100 d-flex justify-content-end mt-5">
{/* <button
className="d-flex align-items-center justify-content-center btn_next_back"
onClick={handleNavigateLogin}
>
<img src={ArrowLeft} alt="" />
</button> */}
<button type="submit" className="btn_next_step" onClick={handleSubmit}>
Suivant
</button>
</div>
</div>
);
};
export default FormIscriptionEtape1;
i tried passing error to onsubmit props but it gives me undefined everytime so the only way that my error passes is the way i am writing the code right now.
Maybe it's because of this typo?
(store) => store.authentification
it should probably be "authentication"
(store) => store.authentication
I am making a react project and when I am trying to sign up through email and password using firebase authentication then this 👇your text error is showing
This is the error I am getting
This is the whole code:
import React,{useState} from 'react';
import { Link, useNavigate } from 'react-router-dom';
import Layout from '../components/layout/Layout';
import {BsFillEyeFill} from "react-icons/bs";
import { getAuth, createUserWithEmailAndPassword , updateProfile} from "firebase/auth";
import {db} from "../firebase.config"
const SignUp = () => {
// to hide password
const [showPassword, setShowPassword] = useState(false);
const [formData, setFormData] = useState({
email:"",
name: "",
password: "",
})
const {name, email, password} = formData;
const navigate = useNavigate();
const onChange = (e) => {
setFormData((prevState) => ({
...prevState,
[e.target.id]: e.target.value,
}));
};
This is my signUp function
const onSubmitHandler= async (e) =>{
e.preventDefault();
try{
const auth= getAuth()
const userCredential = await createUserWithEmailAndPassword(auth,email,password);
const user = userCredential.user
updateProfile(auth.currentUser,{displayName: name})
navigate("/")
alert("Signup Success")
}catch(error){
console.log(error);
}
}
return (
<Layout>
<div className="d-flex align-items-center justify-content-center w-100 mt-5 mb-5">
<form className='bg-light p-4 rounded-3 border border-dark border-3' onSubmit={onSubmitHandler}>
<h4 className='bg-dark p-2 mt-2 text-light rounded-2 text-center'>Sign Up</h4>
<div className="mb-3">
<label htmlFor="exampleInputEmail1" className="form-label">Enter Name</label>
<input
type="text"
defaultValue={name}
id="name"
onChange={onChange}
className="form-control"
aria-describedby="nameHelp"
/>
</div>
<div className="mb-3">
<label htmlFor="exampleInputEmail1" className="form-label">Email address</label>
<input
type="email"
defaultValue={email}
onChange={onchange}
className="form-control"
id="email"
aria-describedby="emailHelp"
/>
<div id="emailHelp" className="form-text">We'll never share your email with anyone else.</div>
</div>
<div className="mb-3">
<label htmlFor="exampleInputPassword1" className="form-label">Password</label>
<input
type={showPassword? "text" : "password"}
defaultValue={password}
onChange={onchange}
className="form-control"
id="password"
/>
<span >Show Password <BsFillEyeFill
className='text-primary ms-2'
style={{cursor: "pointer"}}
onClick={()=> setShowPassword((prevState)=> !prevState)}
/></span>
</div>
<button
type="submit"
className="btn btn-primary">Sign Up</button>
<div>
<h6>Login with Google</h6>
<span>Already User?</span> <Link to="/signin">Login</Link>
</div>
</form>
</div>
</Layout>
)
}
export default SignUp
After going through firebase documentation I have tried various emails but still it is showing the same error.
This is the email I had been using for signUp.
and I tried different emails as well like: piyush#gmail.com, and my personal email too but still it is showing the same error
This is the error message for your error
auth/invalid-email:
The provided value for the email user property is invalid. It must be a string email address.
Check to make sure your onSubmitHandler is within scope of your formData state, because your email and password might be undefined.
Your code has 2 issues,
1: Check the spelling of onChange on email and password field.
2: Change defaultValue to value
Below is the working code:
import React, { useState } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import { BsFillEyeFill } from 'react-icons/bs';
import {
getAuth,
createUserWithEmailAndPassword,
updateProfile,
} from 'firebase/auth';
const Signup = () => {
const [showPassword, setShowPassword] = useState(false);
const [formData, setFormData] = useState({
email: '',
name: '',
password: '',
});
const { name, email, password } = formData;
const navigate = useNavigate();
const onChange = (e: any) => {
setFormData((prevState) => ({
...prevState,
[e.target.id]: e.target.value,
}));
};
const onSubmitHandler = async (e) => {
e.preventDefault();
console.log('email is ', email, password);
try {
const auth = getAuth();
const userCredential = await createUserWithEmailAndPassword(
auth,
email,
password,
);
const user = userCredential.user;
alert('Signup Success');
} catch (error) {
console.log(error);
}
};
return (
<div className="d-flex align-items-center justify-content-center w-100 mt-5 mb-5">
<form
className="bg-light p-4 rounded-3 border border-dark border-3"
onSubmit={onSubmitHandler}
>
<h4 className="bg-dark p-2 mt-2 text-light rounded-2 text-center">
Sign Up
</h4>
<div className="mb-3">
<label htmlFor="exampleInputEmail1" className="form-label">
Enter Name
</label>
<input
type="text"
value={name}
id="name"
onChange={onChange}
className="form-control"
aria-describedby="nameHelp"
/>
</div>
<div className="mb-3">
<label htmlFor="exampleInputEmail1" className="form-label">
Email address
</label>
<input
type="email"
value={email}
onChange={onChange}
className="form-control"
id="email"
aria-describedby="emailHelp"
/>
<div id="emailHelp" className="form-text">
We'll never share your email with anyone else.
</div>
</div>
<div className="mb-3">
<label htmlFor="exampleInputPassword1" className="form-label">
Password
</label>
<input
type={showPassword ? 'text' : 'password'}
value={password}
onChange={onChange}
className="form-control"
id="password"
/>
<span>
Show Password{' '}
<BsFillEyeFill
className="text-primary ms-2"
style={{ cursor: 'pointer' }}
onClick={() => setShowPassword((prevState) => !prevState)}
/>
</span>
</div>
<button type="submit" className="btn btn-primary">
Sign Up
</button>
<div>
<h6>Login with Google</h6>
<span>Already User?</span> <Link to="/signin">Login</Link>
</div>
</form>
</div>
);
};
export default Signup;
`
type here
import React, { useState } from "react";
import { images } from "../../constants";
import { AppWrap, MotionWrap } from "../../wrapper";
import { client } from "../../client";
import "./Footer.scss";
import { SocialMedia } from "../../components";
const Footer = () =\> {
const \[formData, setFormData\] = useState({
name: "",
email: "",
phone: "",
message: "",
});
const \[isFormSubmitted, setIsFormSubmitted\] = useState(false);
const \[loading, setLoading\] = useState(false);
const { name, email, phone, message } = formData;
const handleChangeInput = (e) =\> {
const { name, value } = e.target;
setFormData({ ...formData, [name]: value });
};
const handleSubmit = () =\> {
setLoading(true);
const contact = {
_type: "contact",
name: name,
email: email,
phone: phone,
message: message,
};
client.create(contact).then(() => {
setLoading(false);
setIsFormSubmitted(true);
});
};
return (
\<div className="footer" id="footer"\>
<h2 className="head-text">
Book Inca's Medical Services at
\<span\> Home\</span\>
</h2>
{/\* \<div className="app__footer-cards"\>
\<div className="app__footer-card"\>
<img alt="email" />
<a href="mailto:rajprabhuwork#gmail.com">
karthikraja81195#gmail.com
</a>
\</div\>
\<div className="app__footer-card"\>
<img alt="mobile" />
<a href="tel: +91 (994) 451-6052">
\+91 (994) 451 - 6052
</a>
\</div\>
\</div\> \*/}
{!isFormSubmitted ? (
<div className="app__footer-form app__flex">
<div className="app__flex">
<input
className="p-text"
type="text"
placeholder="Your Name"
name="name"
value={name}
onChange={handleChangeInput}
required
/>
</div>
<div className="app__flex">
<input
className="p-text"
type="email"
placeholder="Your Email"
name="email"
value={email}
onChange={handleChangeInput}
required
/>
</div>
<div className="app__flex">
<input
className="p-text"
type="text"
placeholder="Your Phone"
name="phone"
value={phone}
onChange={handleChangeInput}
required
/>
</div>
<div>
<textarea
className="p-text"
placeholder="Your Message"
value={message}
name="message"
onChange={handleChangeInput}
required
/>
</div>
<button type="button" className="p-text" onClick={handleSubmit}>
{loading ? "Sending" : "Send Message"}
</button>
</div>
) : (
<div>
<h3 className="head-text">
Thank you for getting in touch, You wil be contacted by our
Executive{" "}
</h3>
</div>
)}
<div className="copyright">
<SocialMedia />
<p className="p-text">#2023 INCA All rights reserved</p>
</div>
</div>
);
};
export default AppWrap(
MotionWrap(Footer, "app__footer"),
"contact",
"app__primarybg"
);`
I am trying to display a modal pop up on submit in a form in React. Right now, the invalid email and name modal pops up just fine. The problem is, It will not display the alternate success message if the form was submitted correctly. I also am not sure if it will persist upon successful submission, but can't get past this problem to test it out. Please let me know where I am going wrong. Thanks!!
Contact.js:
import React, { useState } from "react";
import { FaEnvelope } from "react-icons/fa";
import Modal from "./Modal";
const Contact = (props) => {
const [showModal, setShowModal] = useState();
const [enteredName, setEnteredName] = useState("");
const [enteredEmail, setEnteredEmail] = useState("");
const contactHandler = (event) => {
event.preventDefault();
if (enteredName.trim().length === 0 || enteredEmail.trim().length === 0) {
setShowModal({
title: "Invalid Input",
message: "Please enter a valid name and email",
});
return;
}
if (enteredName.trim().length > 0 || enteredEmail.trim().length > 0) {
setShowModal({
title: "Thank You",
message: "Your form as been submitted",
});
return;
}
props.Contact(enteredName, enteredEmail);
setEnteredName("");
setEnteredEmail("");
};
const modalHandler = () => {
setShowModal(null);
};
return (
<div>
{showModal && (
<Modal
title={showModal.title}
message={showModal.message}
onShowModal={modalHandler}
/>
)}
<div className="w-full h-screen main flex justify-center items-center p-4">
<form
onSubmit={contactHandler}
method="POST"
action="https://getform.io/f/8e30048c-6662-40d9-bd8b-da62595ce998"
className="flex flex-col max-w-[600px] w-full"
>
<div className="pb-8">
<p className="text-4xl font-bold inline border-b-4 bdr text-main">
Contact
</p>
<span>
<FaEnvelope className="inline-flex ml-4 text-4xl text-main" />
</span>
<p className="text-main py-2">
Please enter your info below and I will be back with you within 24
hours. You can also email me directly at:
<a
href="mailto:chris.t.williams417#gmail.com"
className="ml-2 font-bold hover:text-[#FFE5b4]"
>
chris.t.williams417#gmail.com
</a>
</p>
</div>
<input
className="form-bg p-2"
type="text"
placeholder="Name"
name="name"
/>
<input
className="my-4 py-2 form-bg"
type="email"
placeholder="Email"
name="email"
/>
<textarea
className="form-bg p-2"
name="message"
rows="10"
placeholder="Message"
></textarea>
<button className="con-btn">Submit</button>
</form>
</div>
</div>
);
};
export default Contact;
Modal.js:
import React from "react";
const Modal = (props) => {
return (
<div>
<div className="backdrop" onClick={props.onShowModal} />
<div className="modalPos">
<div className="header">
<h2>{props.title}</h2>
</div>
<div className="content">
<p>{props.message}</p>
</div>
<div className="actions">
<button onClick={props.onShowModal} className="hero-btn">
Exit
</button>
</div>
</div>
</div>
);
}
export default Modal
*disclaimer : my grammar so bad so i am apologize about that.
i just try your code and when i submit is always invalid, i check it and the state name and email is empty string when i submit because your forgot implement onChangeHanlde in input.
create function to handle onChange
const onChangeHandler = (field, event) => {
if (field == "email") {
setEnteredEmail(event.target.value);
} else if (field == "name") {
setEnteredName(event.target.value);
}
};
and add onChange, value attribute in input tag both name and email
<input
className="form-bg p-2"
type="text"
placeholder="Name"
name="name"
onChange={(e) => {
onChangeHandler("name", e);
}}
value={enteredName}
/>
<input
className="my-4 py-2 form-bg"
type="email"
placeholder="Email"
name="email"
onChange={(e) => {
onChangeHandler("email", e);
}}
value={enteredEmail}
/>
You didn't put
value = {enteredName}
in your input element. so your states will not be set by user's input.
I'm trying to clear/reset the value of a checkbox switch after it becomes disabled. I initially thought I had achieved this by using a React conditional and setting the value to an empty string but if the checkbox had been activated prior to being disabled then that value still gets submitted. This behaviour doesn't seem correct as I was under the impression that disabled input field values do not get submitted?
The React conditional says that if the form is disabled then the value of the checkbox should be empty.
I am using Formik to process forms with Yup schema validation.
Below is my entire code for the form.
Thank you, in advance.
import axios from "axios";
import * as Yup from "yup";
import Head from "next/head";
import Link from "next/link";
import Router from "next/router";
import { useState } from "react";
import Error from "../components/error";
import Layout from "../components/layout";
import Button from "react-bootstrap/Button";
import Spinner from "react-bootstrap/Spinner";
import { Formik, Form, Field, ErrorMessage } from "formik";
var instagram = false;
var twitter = false;
var github = false;
const validationSchema = Yup.object({
firstName: Yup.string()
.max(15, "Must be 15 characters or less"),
email: Yup.string().email("Invalid email address").required("Required"),
username: Yup.string()
.test(
'valid-instagram', "Instagram: may contain only alphanumeric characters, periods, and underscores", function (username){
var instagramRegex = new RegExp(/^(?!.*\.\.)(?!.*\.$)[^\W][\w.]{0,29}$/);
var instagramRes = instagramRegex.test(username)
if (instagramRes) { // if res is true then the username is valid and the switch can be enabled
instagram = false;
return true // return true to tell Yup the field is valid
} else {
instagram = true;
return true // true removes error message
}
}
)
.test(
'valid-twitter', "Twitter: may only contain alphanumeric characters or underscores", function (username){
var twitterRegex = new RegExp(/^[A-Za-z0-9_]{1,15}$/);
var twitterRes = twitterRegex.test(username)
if (twitterRes) { // if res is true then the username is valid and the switch can be enabled
twitter = false;
return true // return true to tell Yup the field is valid
} else {
twitter = true;
return true // true removes error message
}
}
)
.test(
'valid-github', "GitHub: may only contain alphanumeric characters or single hyphens", function (username){
var githubRegex = new RegExp(/^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}$/i);
var githubRes = githubRegex.test(username)
if (githubRes) { // if res is true then the username is valid and the switch can be enabled
github = false;
return true // return true to tell Yup the field is valid
} else {
github = true;
return true // true removes error message
}
}
)
.required("Required"),
acceptTerms: Yup.boolean()
.required("Required")
.oneOf([true], "You must accept the terms and conditions."),
switchGroup: Yup.array().required("At least one option must be selected"),
});
const initialValues = {
firstName: "",
email: "",
username: "",
acceptTerms: false, // added for our checkbox
switchGroup: [], // array for switches
};
export default function Signup() {
const [error, setError] = useState("");
return (
<Layout>
<Head>
<title>Signup - Notify.is</title>
</Head>
<div className="container-center">
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={async (values, { setSubmitting }) => {
const data = new URLSearchParams(values);
const res = await axios
.post("http://localhost:8080/api/signup", data)
.then((response) => {
Router.push("/thanks");
})
.catch((error) => {
setError(error.message);
});
setSubmitting(false);
}}
>
{({ touched, errors, isSubmitting }) => (
<Form className="form">
<h1 className="display-4 pb-3">Get notified</h1>
<div className="form-label-group">
<Field
type="text"
name="firstName"
id="firstName"
placeholder="First name"
className={`form-control ${
touched.firstName && errors.firstName
? "is-invalid"
: null
}`}
/>
<label htmlFor="firstname">First name</label>
<small id="nameHelp" className="form-text text-muted">
Optional
</small>
</div>
<div className="form-label-group">
<Field
type="email"
name="email"
id="email"
placeholder="Email address"
className={`form-control ${
touched.email && errors.email ? "is-invalid" : null
}`}
/>
<ErrorMessage
component="div"
name="email"
className="invalid-feedback"
/>
<small id="emailHelp" className="form-text text-muted">
We'll never share your email with anyone else.
</small>
<label htmlFor="email">Email address</label>
</div>
<div className="form-label-group">
<Field
type="text"
name="username"
id="username"
autoCorrect="off"
autoCapitalize="none"
placeholder="Username"
className={`form-control ${
touched.username && errors.username ? "is-invalid" : null
}`}
/>
<ErrorMessage
component="div"
name="username"
className="invalid-feedback"
/>
<small id="usernameHelp" className="form-text text-muted">
The unavailable username you want.
</small>
<label htmlFor="username">Username</label>
</div>
<div>
<div className="custom-control custom-switch">
<Field
type="checkbox"
name="switchGroup"
id="instagram-switch"
value={instagram ? "" : "instagram"}
disabled={instagram}
className={`custom-control-input ${
touched.switchGroup && errors.switchGroup
? "is-invalid"
: null
}`}
/>
<label
className="custom-control-label"
htmlFor="instagram-switch"
>
Instagram
</label>
</div>
<div className="custom-control custom-switch">
<Field
type="checkbox"
name="switchGroup"
id="twitter-switch"
value={twitter ? "" : "twitter"}
disabled={twitter}
className={`custom-control-input ${
touched.switchGroup && errors.switchGroup
? "is-invalid"
: null
}`}
/>
<label
className="custom-control-label"
htmlFor="twitter-switch"
>
Twitter
</label>
</div>
<div className="custom-control custom-switch">
<Field
type="checkbox"
name="switchGroup"
id="github-switch"
value={github ? "" : "github"}
disabled={github}
className={`custom-control-input ${
touched.switchGroup && errors.switchGroup
? "is-invalid"
: null
}`}
/>
<label
className="custom-control-label"
htmlFor="github-switch"
>
GitHub
</label>
<ErrorMessage
component="div"
name="switchGroup"
className="invalid-feedback"
/>
</div>
<small id="usernameHelp" className="form-text text-muted">
The service(s) we should check with.
</small>
</div>
<div className="custom-control custom-checkbox pt-3 mb-1">
<Field
type="checkbox"
name="acceptTerms"
id="acceptTerms"
className={`custom-control-input ${
touched.acceptTerms && errors.acceptTerms
? "is-invalid"
: null
}`}
/>
<label htmlFor="acceptTerms" className="custom-control-label">
By checking this box you agree to our:
</label>
<ErrorMessage
component="div"
name="acceptTerms"
className="invalid-feedback"
/>
</div>
<span className="grey termslabel">
<Link href="/tos">
<a className="terms" target="_blank">
Terms of Use
</a>
</Link>{" "}
and{" "}
<Link href="/privacy">
<a className="terms" target="_blank">
Privacy Policy
</a>
</Link>
</span>
<Button
className="btn-lg btn-primary btn-block mt-4"
variant="primary"
disabled={isSubmitting, error}
type="submit"
>
{isSubmitting && (
<Spinner
as="span"
animation="grow"
size="lg"
role="status"
aria-hidden="true"
/>
)}
{isSubmitting && <span> Submitting...</span>}
{!isSubmitting && <span>Sign up</span>}
</Button>
{error ? <Error error={error} /> : null}
<p className="mt-4 mb-3 text-muted text-center">
© Notify.is 2020
</p>
</Form>
)}
</Formik>
</div>
<style jsx>
{`
.display-4 {
font-weight: 700;
}
.terms {
text-decoration: underline;
}
.terms:hover {
text-decoration: none;
}
`}
</style>
</Layout>
);
}
I ended up managing to do what I wanted in a different way than originally intended, but it works well.
Using the Boolean variables that change value based on whether a field should be disabled, I did an if statement for each one within the Formik onSubmit prop and changed the values within the array at the indexes of the values that should be omitted.
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={async (values, { setSubmitting }) => {
// if the field was disabled then don't submit switch value
if (instagram) {
var i = values.switchGroup.indexOf("instagram");
values.switchGroup[i] = null
}
if (twitter) {
var i = values.switchGroup.indexOf("twitter");
values.switchGroup[i] = null
}
if (github) {
var i = values.switchGroup.indexOf("github");
values.switchGroup[i] = null
}
const data = new URLSearchParams(values);
const res = await axios
.post("/api/signup", data)
.then((response) => {
Router.push("/thanks");
})
.catch((error) => {
setError(error.message);
});
setSubmitting(false);
}}
>
Check out the FieldArray component. Its' render prop provides an arrayHelper for adding/removing values from fieldArrays.