Modal pop up on submit in React - javascript

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.

Related

How to trigger modal from a different component

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!

How to reset the Modal input states after clicking the modal close button in React?

After giving the input of mobile number when i close the modal, then again after clicking the Form Submit button, input box shows the previously entered number. I believe model captures the previous state by itself and i want to clear it whenever we open the modal.
After entering the OTP input in Modal, if we click on the Edit mobile number and when we again enter the input in mobile number, then previously entered OTP also shows up. I want to clear it after entering the new mobile number.
I have already tried setting the state to ("") on the onclick events but it doesn't help.
I could really use some help.
Code:
export default function Form() {
// form default hooks
const {register,handleSubmit, formState: { errors, isValid },} = useForm({mode: "onChange",criteriaMode: "all",});
const {register: register2,handleSubmit: handleSubmit2,formState: { errors: errors2 },} = useForm({mode: "onChange",});
const [verifyOTPFlag, setVerifyOTPFlag] = useState(true);
//modal hooks
const [mobileNumberInput, setMobileNumberInput] = useState(true);
const [postVerificationMessage, setPostVerificationMessage] = useState();
const [otpVerificationResult, setOtpVerificationResult] = useState(false);
const [show, setShow] = useState(false);
const [otpInput, setShowOtpInput] = useState(false);
const [number, setNumber] = useState("");
const [OTP, setOTP] = useState("");
const [counter, setCounter] = useState(59);
// post office and aadhar hooks
const [districtName, setDistrictName] = React.useState("");
const [stateName, setStateName] = React.useState("");
//-------------------------modal functionalities start-------------------------
const handleClose = () => {
setShow(false);
setShowOtpInput(false);};
const handleShow = () => {
setShow(true);};
const showOtpInput = () => {
getOTP(number);
setOTP("");
setShowOtpInput(true);
setMobileNumberInput(false);
setOtpVerificationResult(false);
};
const onSubmit = (data) => {
data["district"] = districtName;
data["state"] = stateName;
setMobileNumberInput(true);
setPostVerificationMessage("");
setNumber("");
if (verifyOTPFlag) {
if (isValid) {
setShow(true);
} else {}
}
};
const onSubmit2 = () => {
verifyOTP(OTP)
.then((resp) => {
alert("OTP verification Successful");
setPostVerificationMessage(<p className="text-danger">OTP verification Successful</p>);
setVerifyOTPFlag(false);
setOtpVerificationResult(true);
setShowOtpInput(false);
})
.catch((error) => {
setPostVerificationMessage(<p className="text-danger"> OTP verification Failed. Kindly enter the correct OTP</p> )
setOtpVerificationResult(true);
});};
const onClickEditMobileNo = () => {
setShowOtpInput(!otpInput);
setOtpVerificationResult("");
setOTP("");
setMobileNumberInput(true);
};
return (
<div>
<div className="form-group">
<form onSubmit={handleSubmit(onSubmit)}>
<div className="container mt-2">
<label className="control-label">Full Name : </label>
<input
className="text-uppercase input-group input-group-lg form-control"
type="text"
name="username"
{...register("username", {
required: "Username is Required",
pattern: {
value: /^[a-zA-Z0-9\s,\'-\/:&]*$/,
message: "Entered value does not match valid name format",
},
})}
/>
<p className="errorMsg">{errors.username?.message}</p>
<label className="control-label">C/o : </label>
<input
className="text-uppercase input-group input-group-lg form-control"
type="text"
name="careof"
{...register("careof", {
required: "Name of c/o is Required",
pattern: {
value: /^[a-zA-Z0-9\s,\'-\/:&]*$/,
message: "Entered value does not match valid name format",
},
})}
/>
<p className="errorMsg">{errors.careof?.message}</p>
<label className="control-label">House No./Bldg./Apt : </label>
<input
className="text-uppercase input-group input-group-lg form-control"
type="text"
name="houseno"
{...register("houseno", {
required: "House number is Required",
})}
/>
<p className="errorMsg">{errors.houseno?.message}</p>
<div className="text-center">
<button
className="button btn-primary btn px-3 mr-1"
onClick={onSubmit}
>
Form Submit
</button>
</div>
</div>
</form>
<form onSubmit={handleSubmit2(onSubmit2)}>
{/* modal starts */}
<Modal show={show} onHide={handleClose} backdrop="static">
<Modal.Header
style={{
backgroundImage: "linear-gradient(180deg , #3f55c4 , #95a4f0",
}}
closeButton></Modal.Header>
<Collapse in={mobileNumberInput}>
<div
className="input-field-sb mt-4 ml-5"
style={{ width: "80%" }}
>
<input className="input-sb" maxLength="10" type="text" id="mobile"
// onChange={(e) => setNumber(e.target.value)}
{...register2("mobile", {
required: "Mobile number is Required",
pattern: {
value: /^[5-9]\d{9}$/,
message: "Entered value does not match valid name format",
},
onChange: (e) => setNumber(e.target.value),})}/>
<p className="errorMsg">{errors2.mobile?.message}</p>
<label className="label-sb" htmlFor="mobile">Enter Mobile Number: </label>
</div>
</Collapse>
<Modal.Body>
<Collapse in={otpInput}>
<div>
<div className="d-flex justify-content-center">
<p className="text-center"><strong>{" "} We sent you a code to verify your mobile number{" "}</strong>{" "}
<b className="text-danger">{number}</b>
<span className="mobile-text"> Enter your OTP code here</span>
</p>
</div>
<input className="input-sbj" maxLength="6" onChange={(e) => setOTP(e.target.value)}/>
</div>
</Collapse>
<Collapse in={otpVerificationResult}>
<div className="text-center">{postVerificationMessage}</div>
</Collapse>
<div className="d-flex justify-content-center col-md-12">
{otpInput ? (
<Button className="px-5 align-middle mt-4" variant="secondary" onClick={onSubmit2}>{" "} Verify</Button>) : (
<Button className="px-5 align-middle mt-4" variant="secondary"
onClick={errors2.mobile ? null : showOtpInput}>
{" "} Send OTP </Button>)}
</div>
<div className="row">
<div className={otpInput ? "col-sm-6" : "col-sm-6 d-none"}>
<a className="btn">Resend OTP in 00:{counter}</a>
</div>
<div
className={otpInput? "text-right col-sm-6": "text-right col-sm-6 d-none"}>
<a className="btn" onClick={onClickEditMobileNo}> Edit Mobile number </a>
</div>
</div>
</Modal.Body>
</Modal>
</form>
{/* modal ends */}
</div></div>);}
The easiest way would be just adding e.target.reset() in your onSubmit function.
const onSubmit = (data, e) => {
data["district"] = districtName;
data["state"] = stateName;
setMobileNumberInput(true);
setPostVerificationMessage("");
setNumber("");
e.target.reset();
if (verifyOTPFlag) {
if (isValid) {
setShow(true);
} else {}
}
};
also keep the setNumber("") like this. I think this will solve the problem.

How to clear the Modal states after closing it or before opening it again

After giving the input of mobile number when i close the modal, then again after clicking the Form Submit button, input box shows the previously entered number. I believe model captures the previous state by itself and i want to clear it whenever we open the modal.
After entering the OTP input in Modal, if we click on the Edit mobile number and when we again enter the input in mobile number, then previously entered OTP also shows up. I want to clear it after entering the new mobile number.
I have already tried setting the state to ("") on the onclick events but it doesn't help.
I could really use some help.
codesandbox
Code:
export default function Form() {
const {register,handleSubmit, formState: { errors, isValid },} = useForm({mode: "onChange",criteriaMode: "all",});
const {register: register2,handleSubmit: handleSubmit2,formState: { errors: errors2 },} = useForm({mode: "onChange",});
const [verifyOTPFlag, setVerifyOTPFlag] = useState(true);
//modal hooks
const [mobileNumberInput, setMobileNumberInput] = useState(true);
const [postVerificationMessage, setPostVerificationMessage] = useState();
const [otpVerificationResult, setOtpVerificationResult] = useState(false);
const [show, setShow] = useState(false);
const [otpInput, setShowOtpInput] = useState(false);
const [number, setNumber] = useState("");
const [OTP, setOTP] = useState("");
const [counter, setCounter] = useState(59);
// post office and aadhar hooks
const [districtName, setDistrictName] = React.useState("");
const [stateName, setStateName] = React.useState("");
//-------------------------modal functionalities start-------------------------
const handleClose = () => {
setShow(false);
setShowOtpInput(false);};
const handleShow = () => {
setShow(true);};
const showOtpInput = () => {
getOTP(number);
setOTP("");
setShowOtpInput(true);
setMobileNumberInput(false);
setOtpVerificationResult(false);
};
const onSubmit = (data) => {
data["district"] = districtName;
data["state"] = stateName;
setMobileNumberInput(true);
setPostVerificationMessage("");
setNumber("");
if (verifyOTPFlag) {
if (isValid) {
setShow(true);
} else {}
}
};
const onSubmit2 = () => {
verifyOTP(OTP)
.then((resp) => {
alert("OTP verification Successful");
setPostVerificationMessage(<p className="text-danger">OTP verification Successful</p>);
setVerifyOTPFlag(false);
setOtpVerificationResult(true);
setShowOtpInput(false);
})
.catch((error) => {
setPostVerificationMessage(<p className="text-danger"> OTP verification Failed. Kindly enter the correct OTP</p> )
setOtpVerificationResult(true);
});};
const onClickEditMobileNo = () => {
setShowOtpInput(!otpInput);
setOtpVerificationResult("");
setOTP("");
setMobileNumberInput(true);
};
return (
<div>
<div className="form-group">
<form onSubmit={handleSubmit(onSubmit)}>
<div className="container mt-2">
<label className="control-label">Full Name : </label>
<input
className="text-uppercase input-group input-group-lg form-control"
type="text"
name="username"
{...register("username", {
required: "Username is Required",
pattern: {
value: /^[a-zA-Z0-9\s,\'-\/:&]*$/,
message: "Entered value does not match valid name format",
},
})}
/>
<p className="errorMsg">{errors.username?.message}</p>
<label className="control-label">C/o : </label>
<input
className="text-uppercase input-group input-group-lg form-control"
type="text"
name="careof"
{...register("careof", {
required: "Name of c/o is Required",
pattern: {
value: /^[a-zA-Z0-9\s,\'-\/:&]*$/,
message: "Entered value does not match valid name format",
},
})}
/>
<p className="errorMsg">{errors.careof?.message}</p>
<label className="control-label">House No./Bldg./Apt : </label>
<input
className="text-uppercase input-group input-group-lg form-control"
type="text"
name="houseno"
{...register("houseno", {
required: "House number is Required",
})}
/>
<p className="errorMsg">{errors.houseno?.message}</p>
<div className="text-center">
<button
className="button btn-primary btn px-3 mr-1"
onClick={onSubmit}
>
Form Submit
</button>
</div>
</div>
</form>
<form onSubmit={handleSubmit2(onSubmit2)}>
{/* modal starts */}
<Modal show={show} onHide={handleClose} backdrop="static">
<Modal.Header
style={{
backgroundImage: "linear-gradient(180deg , #3f55c4 , #95a4f0",
}}
closeButton></Modal.Header>
<Collapse in={mobileNumberInput}>
<div
className="input-field-sb mt-4 ml-5"
style={{ width: "80%" }}
>
<input className="input-sb" maxLength="10" type="text" id="mobile"
// onChange={(e) => setNumber(e.target.value)}
{...register2("mobile", {
required: "Mobile number is Required",
pattern: {
value: /^[5-9]\d{9}$/,
message: "Entered value does not match valid name format",
},
onChange: (e) => setNumber(e.target.value),})}/>
<p className="errorMsg">{errors2.mobile?.message}</p>
<label className="label-sb" htmlFor="mobile">Enter Mobile Number: </label>
</div>
</Collapse>
<Modal.Body>
<Collapse in={otpInput}>
<div>
<div className="d-flex justify-content-center">
<p className="text-center"><strong>{" "} We sent you a code to verify your mobile number{" "}</strong>{" "}
<b className="text-danger">{number}</b>
<span className="mobile-text"> Enter your OTP code here</span>
</p>
</div>
<input className="input-sbj" maxLength="6" onChange={(e) => setOTP(e.target.value)}/>
</div>
</Collapse>
<Collapse in={otpVerificationResult}>
<div className="text-center">{postVerificationMessage}</div>
</Collapse>
<div className="d-flex justify-content-center col-md-12">
{otpInput ? (
<Button className="px-5 align-middle mt-4" variant="secondary" onClick={onSubmit2}>{" "} Verify</Button>) : (
<Button className="px-5 align-middle mt-4" variant="secondary"
onClick={errors2.mobile ? null : showOtpInput}>
{" "} Send OTP </Button>)}
</div>
<div className="row">
<div className={otpInput ? "col-sm-6" : "col-sm-6 d-none"}>
<a className="btn">Resend OTP in 00:{counter}</a>
</div>
<div
className={otpInput? "text-right col-sm-6": "text-right col-sm-6 d-none"}>
<a className="btn" onClick={onClickEditMobileNo}> Edit Mobile number </a>
</div>
</div>
</Modal.Body>
</Modal>
</form>
{/* modal ends */}
</div></div>)
;}
when applying modal, generally you can use this approach.
when you submit, clear your modal fields states so it will be like it opened for the first time when you open it again.
you can do this for when you toggle or close.
this will mean that whenever you open the modal next time it will open with clean (empty or default) data.

setting the value of more than one input

I am trying to build a login form. I am trying to set up the value of the email & password field individually. But as soon as I try to enter the text in the email text field, the same appears in the password field too. Can I have a solution to this?
Below is the code.
I guess the error is in OnChange fn where I am assigning the same value e.target.value to both the {email, passwaord}.
import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
const LoginPage = () => {
let navigate = useNavigate();
const [credentials, setCredentials] = useState({email:"",password:""});
const onChange = (e) => {
setCredentials({email: e.target.value ,password: e.target.value})
console.log(credentials.email, credentials.password)
}
const goToSignUp = () => {
navigate("/signup");
}
return (
<>
<div className="container my-5">
<div id="loginbody">
<div className="mt-3">
<h2 className="my-3 display-3">Login Here</h2>
<form className="login-form p-5">
<div className="mb-3">
<label for="exampleInputEmail1" className="form-label">
Email address
</label>
<input
type="email"
className="form-control"
id="email"
name="email"
value={credentials.email}
aria-describedby="emailHelp"
onChange={onChange}
/>
<div id="emailHelp" className="form-text">
We'll never share your email with anyone else.
</div>
</div>
<div className="mb-3">
<label for="exampleInputPassword1" className="form-label">
Password
</label>
<input
type="password"
className="form-control"
id="password"
name="password"
value={credentials.password}
onChange={onChange}
/>
</div>
<div className="d-grid gap-2 my-4 col-6 mx-auto">
<button type="submit" className="btn btn-success">
Submit
</button>
</div>
<hr />
<div className="mb-3 text-center">
<div id="emailHelp" className="form-text center my-3">
Didn't have an account ?
</div>
<div className="d-grid gap-2 my-3 col-6 mx-auto">
<button onClick={goToSignUp} className="btn btn-success ">
SignUp Here !
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</>
);
};
export default LoginPage;
You have identified the problem. You need to pass the key to change as well.
Here passing a callback to setState which provides the current state as a parameter, cloning the state object using spread syntax, and then updating the relevant property in the copied object using the passed key as a computed property name.
const LoginPage = () => {
const [credentials, setCredentials] = useState({email:"",password:""});
const onChange = (e, key) => {
setCredentials(prevCredentials => ({...prevCredentials, [key]: e.target.value}))
}
return (
<>
//...
<input
type="email"
className="form-control"
id="email"
name="email"
value={credentials.email}
aria-describedby="emailHelp"
onChange={(e) => onChange(e, 'email')}
/>
//...
<input
type="password"
className="form-control"
id="password"
name="password"
value={credentials.password}
onChange={(e) => onChange(e, 'password')}
/>
//...
</>
);
};
Note: Calling console.log() right after setting state will not log the updated state, the new state values won't be available until the next render cycle. see: useState set method not reflecting change immediately
Use the proper key to the respective fields
const onChange = (e) => {
setCredentials({ ...credentials, [e.target.name]: e.target.value})
console.log(credentials);
}

Displaying a Form From OnClick Button

I am trying to display a form as a popup when I click on a button. I am new to React to I don't really know where to start.
This is the React Component I want to display:
import React, {useState} from 'react';
const initialFormValues = {
firstName: '',
lastName: '',
email: '',
phone: '',
message: ''
}
export default function Contact(){
//set up state
const [contacts, setContacts] = useState([]);
const [formValues, setFormValues] = useState(initialFormValues);
//helper function to trach changes in the input
const inputChange= (name, value) => {
setFormValues({...formValues, [name]: value})
}
const onChange = e => {
const {name, value} = e.target;
inputChange(name, value);
}
//post a new contact to the backend eventually, right now just display the contact to the DOM
const postNewContact = newContact => {
setContacts([newContact, ...contacts])
setFormValues(initialFormValues);
}
const formSubmit = () => {
const newContact = {
firstName: formValues.firstName.trim(),
lastName: formValues.lastName.trim(),
email: formValues.email.trim(),
phone: formValues.phone.trim(),
message: formValues.message.trim()
}
postNewContact(newContact)
}
const onSubmit = e => {
e.preventDefault();
formSubmit();
}
return (
<div className='contact container'>
<h1>This is the contact component</h1>
<form id='contact-form' onSubmit={onSubmit}>
<div className='form-group submit'>
<button id='contact-btn'>SUBMIT CONTACT INFO</button>
</div>
<div className='form-group inputs'>
<label>
First Name:
<input
type='text'
value={formValues.firstName}
onChange={onChange}
name="firstName"
/>
</label>
<label>
Last Name:
<input
type='text'
value={formValues.lastName}
onChange={onChange}
name="lastName"
/>
</label>
<label>
Email:
<input
type='email'
value={formValues.email}
onChange={onChange}
name="email"
/>
</label>
<label>
Phone Number:
<input
type='text'
value={formValues.phone}
onChange={onChange}
name="phone"
/>
</label>
<label>
Message:
<input
type='text'
value={formValues.message}
onChange={onChange}
name="message"
/>
</label>
</div>
</form>
</div>
)
}
I want to display this component as a popup when I click on a "Contact Us" link:
import React from 'react';
import './footer.css'
function Footer()
{
return (
<div className="Footer">
<div className="container">
<div className="row">
<div className="col">
<h4 className="block ">About Us</h4>
</div>
<div className="col">
<h4 className="block" >Contact</h4>
</div>
<div className="col">
<h4><a className="block" href={"https://www.cdc.gov/coronavirus/2019-ncov/faq.html"}>COVID-19 FAQ</a></h4>
</div>
<div className="col">
<h4 className="block"><a className="block" href={"https://www.cdc.gov/coronavirus/2019-ncov/if-you-are-sick/quarantine.html"}>CDC Guidelines</a></h4>
</div>
</div>
</div>
</div>
);
}
export default Footer;
How would I accomplish this? I want the popup to display on click with the following form, and I want the popup to disappear when the user clicks the submit button.
You can either create a popup using HTML + CSS + Javascript as in the link
Custom Popup or use any UI framework like Ant Design and make use of the Modal component.
btn.onclick = function() {
modal.style.display = "block";
}
In react, components are controlled by states in general.
What you will need for toggling the contact form visibility is:
state / setState for the contact form visibility (true / false)
function that triggers state change of the contact form visibility
set the function above at a button with onClick property
With the visibility state, you can set a conditional statement whether the contact form will set the style of display: none or block.

Categories

Resources