So I'm trying to implement this email function into my portfolio, I will insert current code at the bottom. however i keep receiving an error message that says a user ID is required
I went to the site and looked for my user ID, according to some of the docs the user ID should be placed after init() but there is no user ID. I emailed support and they said the user ID was replaced by the public key. which is what i origionally had in that space, however that's the error I receive.
This is my current code that generates the error when I attempt to send mail
import React, { useState, useRef } from "react";
import emailjs from "emailjs-com";
import { init } from "#emailjs/browser";
import "./contact.css";
init("wcnCiEjf9yoZnUt0e");
export default function Contact() {
const [name, setname] = useState("");
const [email, setemail] = useState("");
const form = useRef();
const [message, setmessage] = useState("");
const sendEmail = (e) => {
e.preventDefault();
// console.log(e);
console.log(form.current);
const templateparams = {
from_name: name + " " + email,
to_name: "tamaraandreawilburn#gmail.com",
feedback: message,
};
emailjs.send("service_e0zkrad", "template_7qrzf2e", templateparams).then(
function (response) {
console.log("SUCCESS!", response.status, response.text);
},
function (error) {
console.log("FAILED...", error);
}
);
};
return (
<>
<div>
<div className="contact-me-card row">
<div className="col-lg-6 col-md-5 col-sm-12 left-contact px-2 py-2">
<span className="get-in-touch mx-4 my-5">Get in touch </span>
<div className="py-5 d-flex justify-content-center">
<lottie-player
src="https://assets3.lottiefiles.com/packages/lf20_u25cckyh.json"
background="transparent"
speed="1"
style={{ width: "300px" }}
loop
autoplay
></lottie-player>
</div>
</div>
<div className="col-lg-6 col-md-5 col-sm-12 my-auto">
<form
ref={form}
className="d-flex flex-column card-contact-right"
onSubmit={sendEmail}
>
<div className="input-group my-3 d-flex flex-column">
<label> Name </label>
<input
value={name}
onChange={(e) => {
setname(e.target.value);
}}
type="text"
placeholder="enter your name"
className="input-groups"
/>
</div>
<div className="input-group my-3 d-flex flex-column">
<label>Email </label>
<input
value={email}
onChange={(e) => {
setemail(e.target.value);
}}
type="text"
placeholder="enter your Email"
className="input-groups"
/>
</div>
<div className="input-group my-3 d-flex flex-column">
<label> Message </label>
<textarea
value={message}
onChange={(e) => {
setmessage(e.target.value);
}}
type="text"
placeholder="enter your message"
className="input-groups"
/>
</div>
<div className="input-group my-3 d-flex flex-column">
<input
className="btn btn-success"
type="submit"
value="Send Message"
/>{" "}
</div>
</form>
</div>
</div>
</div>
</>
);
}
Any assistance would be appreciated as i'm completely stuck.
You need to add your public_key as a 4th argument when calling emailjs.send(). For instance:
emailjs.send("service_e0zkrad", "template_7qrzf2e", templateparams, <PUBLIC_KEY>).then(
function (response) {
console.log("SUCCESS!", response.status, response.text);
},
function (error) {
console.log("FAILED...", error);
}
);
This worked for me on a React app. I found it in the docs here: https://www.emailjs.com/docs/examples/reactjs/
Hope that helps!
You can try this solution. This one perfectly worked for me. You should add your personal (PUBLIC_KEY), you can find it inside your email.js (Account) option.
emailjs.sendForm(
'SERVICE_ID',
'TEMPLATE_ID',
form.current,
'PUBLIC_KEY'
)
.then(
(result) => {
alert('message sent successfully...');
console.log(result.text);
},
(error) => {
console.log(error.text);
}
);
Related
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;
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 have a form I am using to allow users to add comments to my site. The form has an input field, a textarea field, and a button. When the button is clicked it runs my addComment() function which adds the name, comment, and timestamp to my firestore collection as a new doc.
It seems like after I click the button to add a comment I have to wait a few seconds before I can post another one. If I try to add a new comment too quickly then request doesn't get sent to my firestore collection, but if I wait a few seconds everything works as expected.
I am curious if this is normal behavior? How can I set it up so users can always post comments without having to wait a few seconds? Can someone explain to me what is happening?
Thanks
Update:
I have been doing some debugging, and I have noticed that both of the functions getVisitorCount() and getUserComments() from the first useEffect run every time I type something into the name or comment input boxes. I have attached screenshots to showcase what is happening.
On the first initial load of the app:
After typing something in the name input box:
Finally, typing something into the comment box as well:
This is not the desired behavior I want these two functions should not be running when I am typing something into either text field. The getUserComments function should only run on the initial render of the app, and whenever the add comment button is clicked.
Could this be what is causing the problems I am experiencing?
import React, { useState, useEffect } from "react";
import { NavBar, Footer, Home, About } from "./imports";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import { db } from "./firebase-config";
import {
collection,
getDocs,
doc,
updateDoc,
addDoc,
Timestamp,
} from "firebase/firestore";
export default function App() {
const [formData, setFormdata] = useState([]);
const [numberOfVisitors, setnumberOfVistors] = useState([]);
const [userComments, setUserComments] = useState([]);
const portfolioStatsRef = collection(db, "portfolio-stats");
const userCommentsRef = collection(db, "user-comments");
const currentNumberOfVisitors = numberOfVisitors.map((visitors) => {
return (
<h2 className="p-3 mb-0 bg-dark bg-gradient text-white" key={visitors.id}>
Number of vistors: {visitors.visitor_count}
</h2>
);
});
const listOfUserComments = userComments.map((comment) => {
return (
<li className="list-group-item" key={comment.id}>
<div className="d-flex w-100 justify-content-center">
<h5 className="mb-1">{comment.name}</h5>
<small>{comment.date.toDate().toString()}</small>
</div>
<p className="d-flex justify-content-center mb-1">{comment.comment}</p>
</li>
);
});
useEffect(() => {
const getVisitorCount = async () => {
const dataFromPortfolioStatsCollection = await getDocs(portfolioStatsRef);
setnumberOfVistors(
dataFromPortfolioStatsCollection.docs.map((doc) => {
return { ...doc.data(), id: doc.id };
})
);
};
const getUserComments = async () => {
const dataFromUserCommentsCollection = await getDocs(userCommentsRef);
setUserComments(
dataFromUserCommentsCollection.docs.map((doc) => {
return { ...doc.data(), id: doc.id };
})
);
};
getVisitorCount();
getUserComments();
}, [numberOfVisitors, portfolioStatsRef, userCommentsRef]);
useEffect(() => {
const updateVisitorCount = async () => {
const portfolioStatsDoc = doc(
db,
"portfolio-stats",
numberOfVisitors[0].id
);
const updatedFields = {
visitor_count: numberOfVisitors[0].visitor_count + 1,
};
await updateDoc(portfolioStatsDoc, updatedFields);
};
if (!numberOfVisitors.length) return;
let sessionKey = sessionStorage.getItem("sessionKey");
if (sessionKey === null) {
sessionStorage.setItem("sessionKey", "randomString");
updateVisitorCount();
}
}, [numberOfVisitors]);
const handleFormData = (event) => {
setFormdata((prevFormData) => {
return {
...prevFormData,
[event.target.name]: event.target.value,
};
});
};
const addComment = async () => {
const newComment = {
name: formData.name,
comment: formData.comment,
date: Timestamp.now(),
};
await addDoc(userCommentsRef, newComment);
};
return (
<>
<div className="d-flex flex-column overflow-hidden min-vh-100 vh-100">
<NavBar />
<div className="row">
<div className="col text-center">
{numberOfVisitors.length === 0 && (
<h2 className="p-3 mb-0 bg-dark bg-gradient text-danger">
Sorry, the Firestore free tier quota has been met for today.
Please come back tomorrow to see portfilio stats.
</h2>
)}
{currentNumberOfVisitors}
</div>
</div>
<div className="bg-image">
<div className="postion-relative">
<main className="flex-grow-1">
<div className="container-fluid p-0">
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
<div className="row">
<div className="center-items col">
<h4 className="">Comments</h4>
</div>
</div>
<div className="row">
<div className="center-items col">
<div className="comments-container">
{userComments.length === 0 && (
<h4 className="text-danger bg-dark m-1 p-1">
Sorry, the Firestore free tier quota has been met
for today. Please come back tomorrow to see
portfilio comments.
</h4>
)}
{listOfUserComments}
</div>
</div>
</div>
<div className="row">
<div className="center-items col">
<h4 className="text-dark">Leave a comment</h4>
</div>
</div>
<div className="row">
<div className="center-items col">
<form className="comment-form">
<div className="form-floating mb-3">
<input
type="text"
className="bg-transparent form-control"
id="floatingInput"
name="name"
onChange={handleFormData}
/>
<label htmlFor="floatingInput">Name</label>
</div>
<div className="form-floating">
<textarea
className="form-textarea-field bg-transparent form-control mb-1"
name="comment"
id="floatingTextarea"
onChange={handleFormData}
/>
<label htmlFor="floatingTextarea">Comment</label>
</div>
<div className="d-grid">
<button
className="btn btn-primary mb-4"
onClick={() => addComment()}
>
Add Comment
</button>
</div>
</form>
</div>
</div>
</Router>
</div>
</main>
</div>
</div>
<Footer />
</div>
</>
);
}
Sign up Form Written in JSX
import './SignUp-Form-CSS.css'
import { Link } from 'react-router-dom';
import { useState, useContext } from 'react';
import AuthContext from '../Context_store/AuthContext/AuthContext';
const SignUp = () => {
const [name, setName] = useState(null);
const [password, setPassword] = useState(null);
const [confirmPassword, setConfirmPassword] = useState(null);
const [image, setImage] = useState(null);
const authCtx = useContext(AuthContext);
const nameChangeHandeler = (event) => {
setName(event.target.value)
}
const passwordChangeHandeler = (event) => {
setPassword(event.target.value)
}
const confirmPasswordChangeHandeler = (event) => {
setConfirmPassword(event.target.value);
}
const imageChangeHandeler = (event) => {
setImage(event.target.files[0]);
console.log(event.target.files[0]);
}
const onSubmitHandeler = (event) => {
event.preventDefault()
// const data = {
// username: name,
// password: password,
// confirmPassword: confirmPassword,
// image: image
// }
const data=new FormData();
data.append("name",name);
data.append("password",password);
data.append("confirmPassword",confirmPassword);
data.append("image",image);
// data.append('username',name);
console.log(data);
authCtx.signup(data)
}
return (
<div class="container">
<div class="row">
<div class="col-lg-10 col-xl-9 mx-auto">
<div class="card flex-row my-5 border-0 shadow rounded-3 overflow-hidden">
<div class="card-img-left d-none d-md-flex">
{/* <!-- Background image for card set in CSS! --> */}
</div>
<div class="card-body p-4 p-sm-5">
<h5 class="card-title text-center mb-5 fw-light fs-5">Register</h5>
<form onSubmit={onSubmitHandeler} encType='multipart/form-data' >
<div class="form-floating mb-3">
<input type="text" class="form-control"
id="floatingInputUsername"
onChange={nameChangeHandeler}
placeholder="myusername" required autofocus />
<label for="floatingInputUsername">Username</label>
</div>
{/* <div class="form-floating mb-3">
<input type="email" class="form-control" id="floatingInputEmail" placeholder="name#example.com" />
<label for="floatingInputEmail">Email address</label>
</div> */}
<hr />
<div class="form-floating mb-3">
<input type="password"
class="form-control"
onChange={passwordChangeHandeler}
id="floatingPassword" placeholder="Password" />
<label for="floatingPassword">Password</label>
</div>
<div class="form-floating mb-3">
<input type="password" class="form-control"
onChange={confirmPasswordChangeHandeler}
id="floatingPasswordConfirm" placeholder="Confirm Password" />
<label for="floatingPasswordConfirm">Confirm Password</label>
</div>
<div>
<label>Select Logo </label>
<input name='image' onChange={imageChangeHandeler} type="file" class="form-control my-4" id="logo" placeholder="Select Logo " />
</div>
<div class="d-grid mb-2">
<button class="btn btn-lg btn-primary btn-login fw-bold text-uppercase" type="submit">Register</button>
</div>
<a class="d-block text-center mt-2 small" >Have an account?<Link class="nav-link" to={'/login'}> Sign In</Link></a>
<hr class="my-4" />
<div class="d-grid mb-2">
<button class="btn btn-lg btn-google btn-login fw-bold text-uppercase" type="submit">
<i class="fab fa-google me-2"></i> Sign up with Google
</button>
</div>
<div class="d-grid">
<button class="btn btn-lg btn-facebook btn-login fw-bold text-uppercase"
// onClick={onSubmitHandeler}
type="submit">
<i class="fab fa-facebook-f me-2"></i> Sign up with Facebook
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
)
}
export default SignUp;
CONTEXT API
import React, { useState } from "react";
import AuthContext from "./AuthContext";
const AuthContextProvider = (props) => {
const [token, setToken] = useState(null);
const login = (loginDetails) => {
}
const signUp = (signUpDetails) => {
console.log("Sign Up Called ");
fetch('http://localhost:5000/register',
{
method:'POST',
body:signUpDetails
// body:JSON.stringify(signUpDetails),
// headers:{
// 'Content-Type': 'application/json'
// }
}).then((resp) => {
return resp.json()
}).then((data) => {
console.log(data);
return data;
}).catch((err) => {
console.log(err);
})
}
const logout = () => {
}
const values = {
login: login,
signup: signUp,
logout: logout,
token: {
token: token,
setToken: setToken
},
isLoggedIn: !!token
}
return (
<div>
<AuthContext.Provider value={values}>
{props.children}
</AuthContext.Provider>
</div>
)
}
export default AuthContextProvider;
But When AT Node server End All Other filed Is recieved as Empty Except image Data
OUTPUT OF DATA SAVED IN DATABASE
And If I follow the Approach in Which I use Simple Object as the data instead of form Data(), I and with header ( that are under // ) I do not receive images at the backend and only receive user info
One solution could be to send the image as a string (base64) to the backend to save the image.
try to implement this in your react:
import { useState } from "react";
import "./styles.css";
export default function App() {
const [img, setImg] = useState("Image string will come here");
const handleChangeImg = (e) => {
console.log(e.target.files[0]);
const reader = new FileReader();
reader.readAsDataURL(e.target.files[0]);
reader.onloadend = () => {
setImg(reader.result);
};
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<input onChange={handleChangeImg} type="file" name="image" />
<button onClick={()=>setImg("Image string will come here")}>Reset</button>
<h1>{img}</h1>
</div>
);
}
Check the code iin codesandbox here.
Related resources:
FileReader
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);
}