I'm trying to implement a toggle function to users sign in and sign up with two buttons (button 1, button 2). Problem is that regardless of which button I click it executes the toggle function. It seems one button click executes both onclick functions.
import React, { useEffect, useState } from "react";
import LockIcon from "#mui/icons-material/Lock";
import VisibilityIcon from "#mui/icons-material/Visibility";
import { GoogleLogin } from "#react-oauth/google";
import jwt_decode from "jwt-decode";
import { useDispatch } from "react-redux";
import { useNavigate } from "react-router-dom";
import "./authStyles.css";
import { signUp, signIn } from "../../action/auth/authAction";
const initialStateForm = {
fName: "",
lName: "",
email: "",
password: "",
confirmPassword: "",
};
const Auth = () => {
const [showPassword, setShowPassword] = useState(true);
const [isSignup, setIsSignup] = useState(false);
const [formData, setFormData] = useState(initialStateForm);
const dispatch = useDispatch();
const navigate = useNavigate();
const switchMode = () => {
setIsSignup((prevIsSignup) => !prevIsSignup);
setShowPassword(false);
console.log("switchMode " + isSignup);
};
const handleSubmit = (e) => {
e.preventDefault();
console.log("handleSubmit " + isSignup);
// if (isSignup) {
// dispatch(signUp(formData));
// } else {
// dispatch(signIn(formData));
// }
};
const handleChnage = (e) => {
e.preventDefault();
setFormData({ ...formData, [e.target.name]: e.target.value });
};
const handleShowPassword = () => {
setShowPassword((prevShowPassword) => !prevShowPassword);
};
const googleSuccess = async (res) => {
const decodeUser = jwt_decode(res.credential);
dispatch({ type: "AUTH", payload: decodeUser });
navigate("/");
};
const googleFailure = (error) => {
console.log(error);
console.log("Google sign in is unsuccessfull");
};
return (
<div>
<div className="sign-form-container">
<LockIcon></LockIcon>
<span>{isSignup ? `Sign Up` : `Sign In`}</span>
{isSignup && (
<>
<input
type="text"
id="fName"
name="fName"
placeholder="First Name"
onChange={handleChnage}
/>
<input
type="text"
id="lName"
name="lName"
placeholder="Last Name"
onChange={handleChnage}
/>
</>
)}
<input
type="email"
id="email"
name="email"
placeholder="Email"
onChange={handleChnage}
/>
<input
type={showPassword ? `password` : `text`}
id="password"
name="password"
placeholder="Password"
onChange={handleChnage}
/>
<VisibilityIcon onClick={handleShowPassword} />
{isSignup && (
<>
<input
type="password"
id="confirmPassword"
name="confirmPassword"
placeholder="Confirm password"
onChange={handleChnage}
/>
</>
)}
<GoogleLogin
onSuccess={googleSuccess}
onFailure={googleFailure}
cookiePolicy="single_host_origin"
></GoogleLogin>
<button type="button" onClick={handleSubmit}> //button 1
{isSignup ? `Sign Up` : `Sign In`}
</button>
<button type="button" onClick={switchMode}> // button 2
{isSignup
? "Already have an account ? Sign In"
: "Don't have and account? Sign Up"}
</button>
</div>
</div>
);
};
export default Auth;
One button needs to execute the respective function only. Not both functions. How to avoid this problem?
Try to nest the elements into a form and declare the first button as type=submit:
return (
<div>
<form className='sign-form-container' onSubmit={handleSubmit}>
...
<button type='submit'>
{isSignup ? `Sign Up` : `Sign In`}
</button>
<button type='button' onClick={switchMode}>
{isSignup
? 'Already have an account ? Sign In'
: "Don't have and account? Sign Up"}
</button>
</form>
</div>
);
Related
I am using "react-mailchimp-subscribe" to integrate with MailChimp and enable users to signup to a mailchimp mailing list upon completing an submitting my form.
However, I get the error:
Uncaught TypeError: onValidated is not a function
When I trigger the function that should submit the form info to MailChimp.
Here is a sample of my code:
import MailchimpSubscribe from "react-mailchimp-subscribe";
...
const CustomForm = ({
className,
topOuterDivider,
bottomOuterDivider,
topDivider,
bottomDivider,
hasBgColor,
invertColor,
split,
status,
message,
onValidated,
...props
}) => {
...
const [email, setEmail] = useState('');
const [fullName, setFullName] = useState('');
const handleSubmit = (e) => {
console.log('handlesubmit triggered')
e.preventDefault();
email &&
fullName &&
email.indexOf("#") > -1 &&
onValidated({
EMAIL: email,
MERGE1: fullName,
});
}
...
<form onSubmit={(e) => handleSubmit(e)}>
<h3>
{status === "success"
? "You have successfully joined the mailing list"
: "Join our mailing list by completing the form below"
}
</h3>
<div className="cta-action">
<Input
id="email"
type="email"
label="Subscribe"
labelHidden hasIcon="right"
placeholder="Your email address"
onChange={e => setEmail(e.target.value)}
value={email}
isRequired
>
</Input>
<Input
id="name"
type="text"
label="Subscribe"
labelHidden hasIcon="right"
placeholder="Your full name"
onChange={e => setFullName(e.target.value)}
value={fullName}
isRequired
>
</Input>
<Input
type="submit"
formValues={[email, fullName]}
/>
</div>
</form>
This is the parent component passing down props to the above:
import React from "react";
import MailchimpSubscribe from "react-mailchimp-subscribe";
const MailchimpFormContainer = props => {
const postURL = `https://*li$%.list-manage.com/subscribe/post?u=${process.env.REACT_APP_MAILCHIMP_U}$id=${process.env.REACT_APP_MAILCHIMP_ID}`;
return (
<div>
<MailchimpSubscribe
url={postURL}
render={({ subscribe, status, message }) => (
<CustomForm
status={status}
message={message}
onValidated={ formData => subscribe(formData) }
/>
)}
/>
</div>
);
};
I have made a signup/login/logout page which works perfectly fine, however I wanted to add an additional field in the register page for user name, and I wanted the username to display in the profile page.
I was able to inset the username field into the register page, and I have a name section on the profile page which also shows up when the profile page loads, however, when I input a user name in the register page, it does not appear in the profile page.
Can anyone please help me figure this out? I really appreciate the help everyone. My first post here :) just recently started my developer journey
// register.js
import { useState } from "react";
import "./forms.css";
import { auth } from "./firebase";
import { useNavigate, Link } from "react-router-dom";
import {
createUserWithEmailAndPassword,
sendEmailVerification,
} from "firebase/auth";
import { useAuthValue } from "./AuthContext";
function Register() {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [error, setError] = useState("");
const navigate = useNavigate();
const { setTimeActive } = useAuthValue();
const validatePassword = () => {
let isValid = true;
if (password !== "" && confirmPassword !== "") {
if (password !== confirmPassword) {
isValid = false;
setError("Passwords does not match");
}
}
return isValid;
};
const register = (e) => {
e.preventDefault();
setError("");
if (validatePassword()) {
// Create a new user with email and password using firebase
createUserWithEmailAndPassword(auth, email, password)
.then(() => {
sendEmailVerification(auth.currentUser)
.then(() => {
setTimeActive(true);
navigate("/verify-email");
})
.catch((err) => alert(err.message));
})
.catch((err) => setError(err.message));
}
setName("");
setEmail("");
setPassword("");
setConfirmPassword("");
};
return (
<div className="center">
<div className="auth">
<h1>Register Account</h1>
{error && <div className="auth__error">{error}</div>}
<form onSubmit={register} name="registration_form">
<input
type="name"
value={name}
placeholder="Enter your user name"
required
onChange={(e) => setName(e.target.value)}
/>
<input
type="email"
value={email}
placeholder="Enter your email"
required
onChange={(e) => setEmail(e.target.value)}
/>
<input
type="password"
value={password}
required
placeholder="Enter your password"
onChange={(e) => setPassword(e.target.value)}
/>
<input
type="password"
value={confirmPassword}
required
placeholder="Confirm password"
onChange={(e) => setConfirmPassword(e.target.value)}
/>
<button type="submit">Register</button>
</form>
<span>
Already have an account?
<Link to="/login">login</Link>
</span>
</div>
</div>
);
}
export default Register;
import "./profile.css";
import { useAuthValue } from "./AuthContext";
import { signOut } from "firebase/auth";
import { auth } from "./firebase";
function Profile() {
const { currentUser } = useAuthValue();
return (
<div className="center">
<div className="profile">
<h1>Profile</h1>
<p>
<strong>Name: </strong>
{currentUser?.name}
</p>
<p>
<strong>Email: </strong>
{currentUser?.email}
</p>
<p>
<strong>Email verified: </strong>
{`${currentUser?.emailVerified}`}
</p>
<span onClick={() => signOut(auth)}>Sign Out</span>
</div>
</div>
);
}
export default Profile;
I have a form,thats data are saved in the state to be sent to the backend server.
i am handling the form with handleSubmit function and useEffect hook, where the handleSubmit prevents the form from being submitted unless it calls the validation function, in the useEffect I check if there are any errors using if condition and then console.log my data.
now I want to post the data hold in the state -the state is sent as a props to me- but I am confused whether to put the request in the HandleSubmit function or in the useEffect inside the body of the if condition.
import react, { Component, useState, useEffect } from 'react';
import {useNavigate } from 'react-router-dom';
import axios from 'axios';
import './sign.css';
const SignA = (props) => {
const navigate = useNavigate();
const [formErrors, setFormErrors] = useState({});
const [isSubmit, setIsSubmit] = useState(false);
const handleSubmit = (err) => {
err.preventDefault();
setFormErrors(validate(props.data));
setIsSubmit(true);
}
useEffect(() => {
console.log(Object.keys(formErrors).length);
if (Object.keys(formErrors).length === 0 && isSubmit) {
console.log('console the props data', props.data)
//here is where I think the post request should be put
if (isSubmit) {
return (navigate('/profileadmin'))
}
}
}, [formErrors])
const validate = (values) => {
const errors = {};
const regex = /^[^\s#]+#[^\s#]+\.[^\s#]{2,}$/i;
if (!values.firstname) {
errors.firstname = 'firstname is required!';
}
if (!values.lastname) {
errors.lastname = 'lastname is required!';
}
if (!values.mobile) {
errors.mobile = 'mobile is required!';
}
if (!values.email) {
errors.email = 'email is required!';
} else if (!regex.test(values.email)) {
errors.email = 'this is not a valid email format!'
}
return errors;
}
return (
<div className='signup'>
<form onSubmit={handleSubmit} >
<div className="container">
<h1>Sign Up</h1>
<div className="name">
<div>
<input
type="text"
placeholder="First name"
name="firstname"
id='firstName'
value={props.data.firstname}
onChange={props.change}
/>
</div>
<div>
<input
type="text"
placeholder="Last name"
name="lastname"
value={props.data.lastname}
onChange={props.change}
/>
</div>
</div>
<p className='errorMsg'>{formErrors.firstname}</p>
<p className='errorMsg'>{formErrors.lastname}</p>
<br />
<div>
<input
type="text"
placeholder="Business mobile number"
name="mobile"
value={props.data.mobile}
onChange={props.change}
/>
<p className='errorMsg'>{formErrors.mobile}</p>
<br />
<input
type="text"
placeholder="Email Adress"
name="email"
value={props.data.email}
onChange={props.change}
/>
<p className='errorMsg'>{formErrors.email}</p>
<br />
</div>
</div>
<br />
<div className="checkbox">
<label>
<input type="checkbox" className="check" />i’ve read and agree with <a href="url" >Terms of service</a>
</label>
</div>
<div className="clearfix">
<button type="submit" className="signupbtn">Sign Up</button>
</div>
</div>
</form >
</div >
)
}
export default SignA;
this is the request
axios.post('', props.data)
.then(res => console.log('post res', res))
.catch(error => {
console.error('There was an error in post request!', error);
});
You don't necessarily need useEffect here.
Here is how you can implement such thing:
Declare a state to hold form values:
const [formData, setFormData] = useState({})
Declare function to set the state:
const handleChange = (name, value) => {
setFormData({...formData, [name]: value})
}
Input onChange to capture:
// handleChange has two parameters
<input
type="text"
placeholder="First name"
name="firstname"
id='firstName'
value={props.data.firstname}
onChange={(event) => handleChange('firstName', event.target.value)}
/>
function for calling post axios post request
const handleSubmit = () => {
//check for validations code here
// if validations are right then post request here
// this will give you all the fields like firstName: "", lastName: ""
let requestBody = {
...formData
}
axios.post("url", requestBody).then((res)=> {
//your code here
})
}
While using react-intl-tel-input-v2 I was getting this error:-× TypeError: Cannot read properties of null (reading 'e') I have install the react-intl-tel-input-v2 from npm Try many things but nothing work if anyone know the solution please help Even if you know any other npm package which help me please suggest
I was getting the error in this part:-
handleChange = (e) => { const { name, value } = e.target this.setState({ [name]: value
This is my code
import React from 'react'
import firebase from './firebase'
import 'firebase/auth';
import "./App.css";
import { getDatabase, ref, child, get } from "firebase/database";
// import PhoneInput from 'react-phone-number-input'
// import $ from 'jquery';
// import intlTelInputUtils from 'jquery';
import ReactIntlTelInput from 'react-intl-tel-input-v2';
import 'intl-tel-input/build/css/intlTelInput.css';
class Login extends React.Component {
handleChange = (e) => {
const { name, value } = e.target
this.setState({
[name]: value
})
this.setState({ phoneNumber: value }, () => {
console.log(this.state.phoneNumber);
});
}
configureCaptcha = () =>{
window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('sign-in-button', {
'size': 'invisible',
'callback': (response) => {
// reCAPTCHA solved, allow signInWithPhoneNumber.
this.onSignInSubmit();
console.log("Recaptca varified")
},
defaultCountry: "IN"
}
);
}
onSignInSubmit = (e) => {
e.preventDefault()
this.configureCaptcha()
const phoneNumber = this.state.mobile
console.log(phoneNumber)
const appVerifier = window.recaptchaVerifier;
const dbRef = ref(getDatabase());
get(child(dbRef, `Users/${phoneNumber}`)).then((snapshot) => {
if (snapshot.exists()) {
firebase.auth().signInWithPhoneNumber(phoneNumber, appVerifier)
.then((confirmationResult) => {
// SMS sent. Prompt user to type the code from the message, then sign the
// user in with confirmationResult.confirm(code).
window.confirmationResult = confirmationResult;
alert('An OTP has been sent to your registered mobile number')
localStorage.setItem("Phone_No", phoneNumber)
console.log(localStorage.getItem('Phone_No'));
}).catch((error) => {
console.error(error);
alert("Oops! Some error occured. Please try again.")
});
}
else {
alert('Sorry, this mobile number is not registered with us. Please use your registered mobile number.');
}
})
}
onSubmitOTP = (e) => {
e.preventDefault()
const code = this.state.otp
console.log(code)
window.confirmationResult.confirm(code).then((result) => {
// User signed in successfully.
const Users = result.user;
console.log(JSON.stringify(Users))
this.props.history.push("/home");
}).catch((error) => {
alert("You have entered wrong code")
});
}
render() {
return (
<div className="Main-header">
<img src="./55k-logo.png" alt="Company Logo" style={{ height: "80px", width: "200px" }} />
<br />
<div>
<h2>Login Form</h2>
<p>Limtless Water. From Unlimited Air.</p>
<form onSubmit={this.onSignInSubmit}>
<div id="sign-in-button"></div>
{/* <PhoneInput */}
<label>Mobile Number</label> <br />
{/* for="phoneNumber" */}
<ReactIntlTelInput
type="tel" id="phone" name="mobile" placeholder="Enter Your Number" required onChange={this.handleChange}
value={this.state.value}
// onChange={this.handleChange}
/>
{/* <input type="tel" id="phone" name="mobile" placeholder="Enter Your Number" required onChange={this.handleChange} /> */}
<div className="buttons">
<button type="submit">Submit</button>
</div>
</form>
</div>
<div>
<form onSubmit={this.onSubmitOTP}>
<label >Code</label> <br />
{/* for="code" */}
<input type="number" name="otp" placeholder="Enter The 6 Digit OTP" required onChange={this.handleChange} />
<div className="buttons" >
<button type="submit">Submit</button>
</div>
</form>
</div>
</div>
)
}
}
export default Login;
I want to get the value when I change it with onChange and created a name and contact number by using the value and setContacts, this app does not cause error but it does not work, Where is the problem? Thanks.
Each new contact in an object has an id, a name and a phone number
const AddUSer = () => {
const {contacts, setcontacts}=useState([]);
const { userName, setUSerName } = useState("");
const { userPhone, setUserPhone } = useState("");
const setName = (e) => {
const value = e.target.value;
return setUSerName(value);
};
const setPhone = (e) => {
const value = e.target.value;
return setUserPhone(value);
};
const handleNewcontact = () => {
const allcontacts = [...contacts];
const newContact = {
id: Math.floor(Math.random() * 1000),
fullName: userName,
phone: userPhone,
};
allcontacts.push(newContact);
setcontacts(allcontacts);
setUSerName("");
setUserPhone("");
}
};
return (
<div className="container">
<form>
<label>Name</label>
<input className="form-control" onChange={(e) => setName} />
<label>Phone</label>
<input className="form-control" onChange={(e) => setPhone} />
<button
onClick={handleNewcontact}
className="btn btn-primary mt-3 mb-4"
>
Save
</button>
</form>
</div>
);
};
export default AddUSer;
You are not passing the event to the function. You can either do
onChange={(e) => setName(e)}
onChange={(e) => setPhone(e)}
but better:
onChange={setName}
onChange={setPhone}
try this. the values are consoled when the user clicks the submit button.
const AddUSer = () => {
const [contact, setContact] = useState({id: '', userName:'', userPhone:''});
function handleNewContact(event) {
setContact({
...contact, id: Math.floor(Math.random() * 1000),
[event.target.name]: event.target.value
});
}
function handleSubmit(event) {
event.preventDefault();
console.log(contact);
}
return (
<div className="container">
<form>
<label>Name</label>
<input className="form-control" name='userName'
onChange={handleNewContact} />
<label>Phone</label>
<input className="form-control" name='userPhone'
onChange={handleNewContact} />
<button
onClick={handleSubmit}
className="btn btn-primary mt-3 mb-4"
>
Save
</button>
</form>
</div>
);
};
export default AddUSer;