For reference you can see this image I need something like this
I am new and learning React JS and I want to take the phone input in +917896541230 or +91 78965412330 in this format, not in this +91 (123)789 654 0 or not in any other format ("I gave +91 as a exam of country code but it will accept all countries code around the world") because then number stored in the database is in above format. I try to include jQuery but it did not work. I don't understand How to do this the npm packages I got all are in a different format which does not work for me.
This is my code
import React from 'react'
import firebase from './firebase'
import "./App.css";
import { getDatabase, ref, child, get } from "firebase/database";
// import PhoneInput from 'react-phone-number-input'
class Login extends React.Component {
// jQuery code
// var phoneNumber = window.intlTelInput(document.querySelector("#phoneNumber"), {
// separateDialCode: true,
// preferredCountries:["in"],
// hiddenInput: "full",
// utilsScript: "//cdnjs.cloudflare.com/ajax/libs/intl-tel-input/17.0.3/js/utils.js"
// });
// $("#getCode").click(function() {
// var full_num = phoneNumber.getNumber(intlTelInputUtils.numberFormat.E164);
// $("input[name='phoneNumber[full]'").val(full_num);
// localStorage.setItem("Phone_No", full_num)
// });
//
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
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" */}
<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;
try React Moduel
first install package
npm i react-phone-input-2
second require it on page
import PhoneInput from 'react-phone-input-2'
third import css
import 'react-phone-input-2/lib/style.css'
in side return (
<PhoneInput
country={"in"}
/>
)
Related
I'm trying to set up a hard coded authentication in react when a user logs in through a form. With the code I have right now, it always returns the "else" statement, even if it meets the requirements for the "if".
I'm trying to pass in both the handleSubmit function and the authenticate function in the onClick for the submit button. The other issue I'm running into is that when I pass in both functions, it doesn't reset state on the username and password fields on the form.
import React, { useState } from "react";
import "./Login.css";
function Login() {
const [name, setName] = useState("");
const [uname, setUname] = useState("");
const [pword, setPword] = useState("");
const Employee = {
id: 12345,
password: "abcde",
};
function handleInput(e) {
setName(e.target.value);
}
function handleSubmit(e) {
e.preventDefault();
setUname("");
setPword("");
}
function authenticate() {
if (uname === Employee.id && pword === Employee.password) {
console.log("Success! Logged in.");
} else {
console.log("Invalid Employee ID and/or password");
}
}
return (
<div className="login-card">
Hello {name}
<div className="username" onChange={handleInput}>
<input
type="input"
className="username-input"
placeholder="Employee ID"
onChange={(e) => setUname(e.target.value)}
value={uname}
autoComplete="off"
/>
</div>
<div className="password">
<input
className="password-input"
type="password"
placeholder="Password"
onChange={(e) => setPword(e.target.value)}
value={pword}
autoComplete="off"
/>
</div>
<button
className="submit-btn"
type="submit"
onClick={(handleSubmit, authenticate)}
>
Login
</button>
</div>
);
}
export default Login;
EDIT: A combination of all three answers worked. Had to wrap the div in a form, call the authenticate function inside of handleSubmit, and use "==" instead of "===" on checking for the Employee.id:
import React, { useState } from "react";
import "./Login.css";
function Login() {
const [name, setName] = useState("");
const [uname, setUname] = useState("");
const [pword, setPword] = useState("");
const Employee = {
id: 12345,
password: "abcde",
};
function handleInput(e) {
setName(e.target.value);
}
function authenticate() {
if (uname == Employee.id && pword === Employee.password) {
console.log("Success! Logged in.");
} else {
console.log("Invalid Employee ID and/or password");
}
}
function handleSubmit(e) {
authenticate();
e.preventDefault();
setUname("");
setPword("");
}
return (
<div className="login-card">
Hello {name}
<form onSubmit={handleSubmit}>
<div className="username" onChange={handleInput}>
<input
type="input"
className="username-input"
placeholder="Employee ID"
onChange={(e) => setUname(e.target.value)}
value={uname}
autoComplete="off"
/>
</div>
<div className="password">
<input
className="password-input"
type="password"
placeholder="Password"
onChange={(e) => setPword(e.target.value)}
value={pword}
autoComplete="off"
/>
</div>
<button className="submit-btn" type="submit" onClick={handleSubmit}>
Login
</button>
</form>
</div>
);
}
export default Login;
import React, { useState } from "react";
function Login() {
const [name, setName] = useState("");
const [uname, setUname] = useState("");
const [pword, setPword] = useState("");
const Employee = {
id: "12345", //string
password: "abcde"
};
function handleInput(e) {
setName(e.target.value);
}
function handleSubmit(e) {
e.preventDefault();
setUname("");
setPword("");
}
function authenticate(e) {
if (uname === Employee.id && pword === Employee.password) {
console.log("Success! Logged in.");
} else {
console.log("Invalid Employee ID and/or password");
}
handleSubmit(e);
}
console.log(uname, pword);
return (
<div className="login-card">
Hello {name}
<div className="username" onChange={handleInput}>
<input
type="input"
className="username-input"
placeholder="Employee ID"
onChange={(e) => setUname(e.target.value)}
value={uname}
autoComplete="off"
/>
</div>
<div className="password">
<input
className="password-input"
type="password"
placeholder="Password"
onChange={(e) => setPword(e.target.value)}
value={pword}
autoComplete="off"
/>
</div>
<button className="submit-btn" type="submit" onClick={authenticate}>
Login
</button>
</div>
);
}
export default Login;
You are trying to compare id which is number but e.target.value always return string.So === does strict checking with value as well as its type and it fails since "12345" === 12345 will be false.
you need to place those divs inside a form tag
then you can assign "onSubmit" to the form
and also you can do all in one function you don't need two
try this and tell me if its works:
function handleSubmit = (e) => {
e.preventDefault();
if(uname === Employee.id && pword === employee.password){
console.log("logged in")
setname(uname);
setUname("")
setPword("")
} else if(!uname && !pword){
console.log("please fill the fields")
}
else {
console.log("invalid login");
setUname("")
setPword("")
}
}
<div className="login-card">
Hello {name}
<form onSubmit={handleSubmit}>
<div className="username">
<input
type="input"
className="username-input"
placeholder="Employee ID"
onChange={(e) => setUname(e.target.value)}
value={uname}
autoComplete="off"
/>
</div>
<div className="password">
<input
className="password-input"
type="password"
placeholder="Password"
onChange={(e) => setPword(e.target.value)}
value={pword}
/>
</div>
<button type="submit">submit</button>
</form>
</div>
</div>
This question already has answers here:
Firebase Prevent Creating Account Before Email Verification
(1 answer)
Firebase - Freeze an account until email is verified
(1 answer)
Firebase email verification not working as expected, without verification the user is able to login
(4 answers)
Closed 8 months ago.
I'm trying to create a Firebase authentication system in my React web app. I know how to register an account and I know how to send a verification email out. Upon registration it sends the verification email which is fine, but the account gets added to the Firebase console database before the user has even verified it. I want it to be such that only verified accounts are added to the database.
Here is my code:
import React, { useState, useEffect, useRef } from 'react'
import './join.css'
import { Link, useNavigate } from 'react-router-dom'
import { auth } from '../firebase'
import { createUserWithEmailAndPassword, onAuthStateChanged, sendEmailVerification } from "firebase/auth"
export default function Join() {
const [registerEmail, setRegisterEmail] = useState('');
const [registerPassword, setRegisterPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');
const [user, setUser] = useState({});
const verificationMessage = useRef();
useEffect(() => {
onAuthStateChanged(auth, (currentUser) => {
setUser(currentUser);
});
}, [])
const navigate = useNavigate();
const register = async () => {
try {
const user = await createUserWithEmailAndPassword(auth, registerEmail, registerPassword);
console.log(user);
} catch (error) {
console.log(error.message);
}
}
const handleSubmit = event => {
if (registerPassword === confirmPassword) {
sendEmailVerification(auth.currentUser);
verificationMessage.current.style.display = 'block';
register();
event.preventDefault();
}
else {
alert('Passwords do not match, please try again!');
event.preventDefault();
}
}
return (
<>
<div className="signup-div">
<h2>Sign Up</h2>
<form onSubmit={handleSubmit}>
<fieldset>
<label className='labels'>Email:</label><br />
<input placeholder='Please enter your email' type="email" value={registerEmail} onChange={e => setRegisterEmail(e.target.value)} required />
</fieldset>
<fieldset>
<label className='labels'>Set Password:</label><br />
<input placeholder='Create password' type="password" value={registerPassword} onChange={e => setRegisterPassword(e.target.value)} required />
</fieldset>
<fieldset>
<label className='labels'>Re-type password to confirm:</label><br />
<input placeholder="Confirm password" type="password" value={confirmPassword} onChange={e => setConfirmPassword(e.target.value)} required />
</fieldset>
<button type="submit">Sign Up</button>
</form>
<div>
Already have an account? <Link to="/login">Log In</Link>
</div>
</div>
<div className='verification-message' ref={verificationMessage}>Welcome aboard! Please check your inbox and click the link in our verification email to verify your account. This could take upto a few minutes to arrive.</div>
</>
)
}
I have a form with a button to submit it, and I also use the same button to route to another page.
the button work in routing and when I remove the Navlink tag it submits the form. but it does not submit it when the Navlink tags are there and does not show the validation error msgs as well it just route the page.
any help on how to get the two actions to work?
here is my code
import react, { Component, useState, useEffect } from 'react';
import { NavLink } from 'react-router-dom';
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { faEyeSlash, faEye } from "#fortawesome/free-solid-svg-icons";
import './sign.css';
const Sign = () => {
//state to be sent to backend
const intialValues = { firstname: "", lastname: "", mobile: "", email: "", password: "", cpassword: "" };
const [formValues, setFormValues] = useState(intialValues);
const [formErrors, setFormErrors] = useState({});
const [isSubmit, setIsSubmit] = useState(false);
const handleChange = (e) => {
console.log(e.target.value);
const { name, value } = e.target;
setFormValues({ ...formValues, [name]: value });
}
const handleSubmit = (err) => {
err.preventDefault();
setFormErrors(validate(formValues));
setIsSubmit(true);
}
useEffect(() => {
if (Object.keys(formErrors).length === 0 && isSubmit) {
console.log(formValues);
}
}, [formErrors])
const validate = (values) => {
const errors = {};
if (!values.firstname) {
errors.firstname = 'firstname is required!';
}
if (!values.lastname) {
errors.lastname = 'lastname is required!';
}
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={formValues.firstname}
onChange={handleChange}
/>
</div>
<div>
<input
type="text"
placeholder="Last name"
name="lastname"
value={formValues.lastname}
onChange={handleChange}
/>
</div>
</div>
<p className='errorMsg'>{formErrors.firstname}</p>
<p className='errorMsg'>{formErrors.lastname}</p>
<br />
<div className="clearfix">
<NavLink to='/profileclient'>
<button type="submit" className="signupbtn">Sign Up</button>
</NavLink>
</div>
</div>
</form>
</div>
)
}
export default Sign;
then I tried to use useNavigate so I modified these lines, and it does navigate to the other page but in the console, it gives me a warning "Form submission canceled because the form is not connected", it does not log the state objects.
const navigate = useNavigate();
<div className="clearfix">
<button type="submit" className="signupbtn" onClick={() => { navigate('/profileclient') }}>Sign Up</button>
</div>
I discovered the solution.
the main problem was that I tried to trigger functions at the same time by clicking on a button, while the submission needs time first before the navigation could happen, this is why it did not submit the form but only navigated. in order to solve the ambiguous behavior, I have put the navigation function call in if statement to make sure the submission is done or not before the navigation is executed. I have also changed the place where I call the navigate function, rather than calling it on the button onClick attribute, I placed it in the useEffect where I check if there are no errors you can submit the form and after submitting it you can navigate to another page.
this is the part of my code that made it work well.
if (isSubmit) {
return (navigate('/profileclient'));
}
and here is my full code
import react, { Component, useState, useEffect } from 'react';
import { NavLink, useNavigate } from 'react-router-dom';
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { faEyeSlash, faEye } from "#fortawesome/free-solid-svg-icons";
import './sign.css';
const SignC = () => {
const navigate = useNavigate();
//state to be sent to backend
const intialValues = { firstname: "", lastname: "", mobile: "", email: "", password: "", cpassword: "" };
const [formValues, setFormValues] = useState(intialValues);
const [formErrors, setFormErrors] = useState({});
const [isSubmit, setIsSubmit] = useState(false);
const [passwordShown, setPasswordShowen] = useState(false);
const [cPasswordShown, setCPasswordShowen] = useState(false);
const [eyeShowen, setEyeShowen] = useState(false);
const [cEyeShowen, setCEyeShowen] = useState(false);
const handleChange = (e) => {
console.log(e.target.value);
const { name, value } = e.target;
setFormValues({ ...formValues, [name]: value });
}
const handleSubmit = (err) => {
err.preventDefault();
setFormErrors(validate(formValues));
setIsSubmit(true);
}
useEffect(() => {
if (Object.keys(formErrors).length === 0 && isSubmit) {
console.log(formValues);
if (isSubmit) {
return (navigate('/profileclient'));
}
}
}, [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!'
}
if (!values.password) {
errors.password = 'password is required!';
} else if (values.password.length < 4) {
errors.password = 'password must be more than 4 characters';
} else if (values.password.length > 10) {
errors.password = 'password must not exceeds 10 characters';
}
if (!values.cpassword) {
errors.cpassword = 'password confirmation is required!';
} else if (values.cpassword != values.password) {
errors.cpassword = 'confirmation password does not match!';
}
return errors;
}
const togglePassword = () => {
setPasswordShowen(!passwordShown);
toggleEye();
}
const toggleCPassword = () => {
setCPasswordShowen(!cPasswordShown);
toggleCEye();
}
const toggleEye = () => {
setEyeShowen(!eyeShowen);
}
const toggleCEye = () => {
setCEyeShowen(!cEyeShowen);
}
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={formValues.firstname}
onChange={handleChange}
/>
</div>
<div>
<input
type="text"
placeholder="Last name"
name="lastname"
value={formValues.lastname}
onChange={handleChange}
/>
</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={formValues.mobile}
onChange={handleChange}
/>
<p className='errorMsg'>{formErrors.mobile}</p>
<br />
<input
type="text"
placeholder="Email Adress"
name="email"
value={formValues.email}
onChange={handleChange}
/>
<p className='errorMsg'>{formErrors.email}</p>
<br />
<div className="password">
<input
type={passwordShown ? 'text' : 'password'}
placeholder="Password"
name="password"
id='password'
value={formValues.password}
onChange={handleChange}
/>
<FontAwesomeIcon
icon={eyeShowen ? faEye : faEyeSlash}
id='togglePassword'
onClick={togglePassword}
/>
<p className='errorMsg'>{formErrors.password}</p>
<br />
<input
type={cPasswordShown ? 'text' : 'password'}
placeholder="Confirm Password"
name="cpassword"
id='Cpassword'
value={formValues.cpassword}
onChange={handleChange}
/>
<FontAwesomeIcon
icon={cEyeShowen ? faEye : faEyeSlash}
id='toggleCPassword'
onClick={toggleCPassword}
/>
<p className='errorMsg'>{formErrors.cpassword}</p>
</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 SignC;
I am trying to make a button which submit the form and then navigate
to another page.
The important distinction here is the then. When you wrap a link around a button both elements are clicked.
<NavLink to='/profileclient'>
<button type="submit" className="signupbtn">Sign Up</button>
</NavLink>
The link tries to navigate at the same time the form is processing its onSubmit handler.
If you want to conditionally navigate at the after submitting the form then you need to move the navigation logic there. Use the useHistory or useNavigate (depending on react-router-dom version, v5 the former, v6 the latter). There's also no need to store an isSubmit state, you can simply check the validation result in the submit handler and conditionally set the form errors or navigate to the next page.
Example:
const Sign = () => {
const navigate = useNavigate();
...
const handleSubmit = (event) => {
event.preventDefault();
const errors = validate(formValues);
if (Object.values(errors).length) {
setFormErrors(errors);
} else {
navigate("/profileclient");
}
};
const validate = (values) => {
const errors = {};
...
return errors;
};
return (
<div className="signup">
<form onSubmit={handleSubmit}>
<div className="container">
<h1>Sign Up</h1>
...
<div className="clearfix">
<button type="submit" className="signupbtn">
Sign Up
</button>
</div>
</div>
</form>
</div>
);
};
So the problem I am facing is this. Here I have created PaymentForm with Stripe. So when I am not entering the input value of CardHolder name, and when I press the Purchase button it should display the <h1>Please enter your cardholder name</h1> but it is not doing it. I just want to create a test of Cardholder name, I know the documentation of Stripe is showing real approaches. Where could the error be located?
Payment form
import React,{useContext, useEffect, useState} from 'react'
import {CardElement, useStripe, useElements } from"#stripe/react-stripe-js"
import { CartContext } from '../../context/cart'
import { useHistory, Link } from "react-router-dom";
const PaymentForm = () => {
const { total} = useContext(CartContext)
const {cart, cartItems}= useContext(CartContext)
const history = useHistory()
const {clearCart} = useContext(CartContext)
const [nameError, setNameError]=useState(null)
const [name, setName] = React.useState("");
const [succeeded, setSucceeded] = useState(false);
const [error, setError] = useState(null);
const [processing, setProcessing] = useState('');
const [disabled, setDisabled] = useState(true);
const [clientSecret, setClientSecret] = useState('');
const stripe = useStripe();
const elements = useElements();
useEffect(() => {
// Create PaymentIntent as soon as the page loads
window
.fetch("http://localhost:5000/create-payment-intent", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({items: [{cart}]})
})
.then(res => {
return res.json();
})
.then(data => {
setClientSecret(data.clientSecret);
});
}, [cart]);
const cardStyle = {
style: {
base: {
color: "#32325d",
fontFamily: 'Arial, sans-serif',
fontSmoothing: "antialiased",
fontSize: "16px",
"::placeholder": {
color: "#32325d"
}
},
invalid: {
color: "#fa755a",
iconColor: "#fa755a"
}
}
};
const handleChange = async (event) => {
setDisabled(event.empty);
setError(event.error ? event.error.message : "");
};
const handleChangeInput = async (event) => {
setDisabled(event.empty);
setNameError(event.nameError ? event.nameError.message : "");
setName(event.target.value)
};
const handleSubmit = async ev => {
ev.preventDefault();
setProcessing(true);
const payload = await stripe.confirmCardPayment(clientSecret, {
payment_method: {
card: elements.getElement(CardElement)
}
});
if (payload.error) {
setError(`Payment failed ${payload.error.message}`);
setProcessing(false);
} else {
setNameError(null)
setError(null);
setProcessing(false);
setSucceeded(true)
clearCart()
}
};
useEffect(()=>{
setTimeout(() => {
if(succeeded){
history.push('/')
}
}, 3000);
},[history, succeeded])
console.log(name)
return (
<form id="payment-form" onSubmit={handleSubmit}>
<h2>Checkout</h2>
<div className='payment__cont'>
<label>Cardholder Name </label>
<input
placeholder='Please enter your Cardholder name'
type="text"
id="name"
value={name}
onChange={handleChangeInput}
/>
</div>
<div className="stripe-input">
<label htmlFor="card-element">
Credit or Debit Card
</label>
<p className="stripe-info">
Test using this credit card : <span>4242 4242 4242 4242</span>
<br />
enter any 5 digits for the zip code
<br />
enter any 3 digits for the CVC
</p>
</div>
<CardElement id="card-element" options={cardStyle} onChange={handleChange} />
<div className='review__order'>
<h2>Review Order</h2>
<h4>Total amount to pay ${total}</h4>
<h4>Total amount of items {cartItems}</h4>
<button
className='purchase__button'
disabled={processing || disabled || succeeded}
id="submit"
>
<span id="button-text">
{processing ? (
<div className="spinner" id="spinner"></div>
) : (
"Complete purchase"
)}
</span>
</button>
<button className='edit__button'onClick={()=> {history.push('/cart')}}>Edit Items</button>
</div>
{error && (
<div className="card-error" role="alert">
{error}
</div>
)}
{nameError && (
<div className="card-error" role="alert">
<h1>Please enter yor card holder name</h1>
</div>
)}
<p className={succeeded ? "result-message" : "result-message hidden"}>
Payment succeeded
{''}
<h1>Redirecting you yo the home</h1>
</p>
</form>
);
}
export default PaymentForm
You still need to validate your name input yourself. Stripe doesn't do that for you
Your handleChangeInput handler only fires when you write to your name input, and you're treating the event as if it's fired from a Stripe component, but it's not, so try this:
// Validates name input only
const handleChangeInput = async (event) => {
const { value } = event.target;
// Disable when value is empty
setDisabled(!value);
// Set the error if value is empty
setNameError(value ? "" : "Please enter a name");
// Update form value
setName(value)
};
I'm not sure what you want to do is possible with Stripe elements as cardholder name isn't actually part of it. You'll need to handle it yourself.
An alternative way of ensuring the name field is entered prior to the card element being pressed would be to force input into cardholder name field before displaying/enabling the Stripe Card Element. This way you can be more certain the the name has been entered (and then you can do what you like with it) before the card element is pressed. You could do this a lot of ways, but for example in your render:
{name.length >= 10 ? ( //Check length of name
<CardElement id="card-element" options={cardStyle} onChange={handleChange} />
) : (
<span>Please enter your cardholder name.</span> // do nothing if check not passed
)}
This is a really simple example but it checks the length of name and then if greater than or equals ten characters makes the card element visible. You could instead use your handleChangeInput to set a boolean state (true or false) on button press or something; it would be better to make this more robust.
edit: some clarifications.
I'm new to React and have written the following form which sends the data to Firebase, this part works but on submit I want to redirect to /thankyou.html which is outside of the react app.
Can anyone advise how I redirect after submit please?
My form is as follows:
import React, { Component } from 'react';
import firebase from '../firebase.js';
class Form extends Component {
constructor(){
super();
this.state = {
name : "",
email : "",
phone : "",
message : "",
formError: false
}
}
getName = (e) =>{
let username = e.target.value;
this.setState({
name: username
});
}
getPhone = (e) =>{
let userphone = e.target.value;
this.setState({
phone: userphone
});
}
getEmail = (e) =>{
let userEmail = e.target.value;
//the most important thing is that we use a RegEx
//in order to manage the input of the email
//at least we can get a some what valid email
if(userEmail.match(/^([a-zA-Z0-9_\-\.]+)#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/)){
this.setState({
email: userEmail
});
}else{
this.setState({
email: ""
});
}
}
getDescription = (e) =>{
let userMessage = e.target.value;
this.setState({
message: userMessage
});
}
//send the form
submitForm = (e) =>{
e.preventDefault()
const itemsRef = firebase.database().ref('items');
if(this.state.name === "" || this.state.email === "" || this.state.phone === "" || this.state.message === "" ){
this.setState({
formError: true
})
return false;
}else{
this.setState({
formError: false
})
const item = {
Name: this.state.name,
Email: this.state.email,
Phone: this.state.phone,
Message: this.state.message
}
itemsRef.push(item);
this.setState({
name: '',
email: '',
phone: '',
message: ''
})
}
}
render() {
return (
<form onSubmit={this.handleSubmit}>
{/* I am just sending a basic error message */}
{this.state.formError &&
<p className="error">
Fill all the input fields please.
</p>
}
<div>
<label htmlFor="name">Name</label>
<input type="text" name="name" placeholder="Your name here please" onChange={this.getName} />
</div>
<div>
<label htmlFor="email">Email</label>
<input type="email" name="email" placeholder="We will contact you after reviewing your message" onChange={this.getEmail} />
</div>
<div>
<label htmlFor="phone">Phone</label>
<input type="phone" name="phone" placeholder="We will contact you after reviewing your message" onChange={this.getPhone} />
</div>
<div>
<label htmlFor="name">Message</label>
<textarea onChange={this.getDescription} maxLength="450"></textarea>
</div>
<div>
<p>We will answer as soon as possible</p>
<input type="submit" name="submit" value="Send" onClick= {this.submitForm} />
</div>
</form>
);
}
}
export default Form;
in firebase push() can have a callback function as a second parameter which you can use in your case to check whenever the save process to firebase is done redirect to thank you page.
so after submitting the form and save to firebase, you can redirect to another page like that :
itemsRef.push(item, ()=>{
window.location.href = "/thankyou.html"; // similar behavior as clicking on a link
});
Use react-router-dom npm package.
import {withRouter, BrowserRouter } from 'react-router-dom';
Wrap your App.js component with BrowserRouter
<BrowserRouter><App /></BrowserRouter >
Now Wrap your component with withRouter where you have submit handler function.
export default withRouter(yourcomponentname);
submitForm = (e) =>{
this.props.history.push('/url');
}
Try this in your submitForm function after doing all stuff. hope it will help you.
document.location = "/thankyou.html" if the file is in root directory, and document.location = "thankyou.html" if the file is in relative directory.
submitForm = (e) =>{
this.props.history.push('/thankyou');
}