So i have this react / node app where basically when I hit register after entering in all my details, it takes me to the stripe checkout page. However, i've been reading firebase goes into a cold start, after 2-3 minutes of no invocations. This is a problem, because we don't expect to get large traffic into our app for another 6 months, which means that there isn't going to be a person using the app every 2-3 minutes.
Right now, during that limbo period between registration and stripe checkout, it goes into a white screen, for like 8 seconds. How can I get this to be a loading screen instead, like one of those react spinning loaders as a temp fix so our customers don't get worried the app is breaking on them?
here's my code for the registration page and then the function that calls stripe:
let firestore = firebase.firestore()
const FormItem = Form.Item
var userIDStripeSubmit = ""
class RegistrationForm extends React.Component {
state = {
confirmDirty: false,
}
onSubmit = (event) => {
event.preventDefault();
this.props.form.validateFields((err, values) => {
if (err) return
const email = this.props.form.getFieldValue('email')
const passwordOne = this.props.form.getFieldValue('password1')
const firstName = this.props.form.getFieldValue('First Name')
const lastName = this.props.form.getFieldValue('Last Name')
const companyName = this.props.form.getFieldValue('Company Name')
const {
history,
} = this.props
AuthorizationHome.doCreateUserWithEmailAndPassword(email, passwordOne)
.then((authUser) => facades.userFacade().doCreateUser(authUser.user.uid, email))
.catch(error => {
this.setState({'error': error})
})
// adding into profiledata collection
// var userID = ""
firebase.auth().onAuthStateChanged((user) => {
if(user) {
console.log(user.uid)
userIDStripeSubmit = user.uid
console.log("userid inside firebase auth is" + user.uid)
// var firstNameFromField =
firestore.collection('profiledata').doc(user.uid).set({
firstname: firstName,
lastname: lastName,
companyname: companyName,
accountStatus: "inactive",
})
.catch(error => {
alert(error.message);
});
createCheckoutSession(user.uid)
}
})
// firestore collection query
})
}
handleConfirmBlur = (e) => {
const value = e.target.value;
this.setState({ confirmDirty: this.state.confirmDirty || !!value });
}
compareToFirstPassword = (rule, value, callback) => {
const form = this.props.form;
if (value && value !== form.getFieldValue('password1')) {
callback('Passwords do not match!');
} else {
callback();
}
}
validateToNextPassword = (rule, value, callback) => {
const form = this.props.form;
if (value && this.state.confirmDirty) {
form.validateFields(['password2'], { force: true });
}
callback();
}
render() {
const { getFieldDecorator } = this.props.form
const { error } = this.state
return (
<Form onSubmit={this.onSubmit} hideRequiredMark={true} className="registration-form" style={{ marginBottom: "0px" }}>
{ error && <Alert type="error" message={error.message}/> }
<FormItem label="Email" colon={false} style={{ marginBottom: "0px" }}>
{getFieldDecorator('email', {
rules: [{
type: 'email', message: 'Invalid email address',
}, {
required: true, message: 'Please input your email address',
}],
})(
<Input placeholder="Enter email" />
)}
</FormItem>
{/* */}
<FormItem label="First Name" colon={false} style={{ marginBottom: "0px" }}>
{getFieldDecorator('First Name', {
rules: [{
required: true, message: 'Please enter your First Name',
}],
})(
<Input type="text" placeholder="Enter Your First Name"/>
)}
</FormItem>
<FormItem label="Last Name" colon={false} style={{ marginBottom: "0px" }}>
{getFieldDecorator('Last Name', {
rules: [{
required: true, message: 'Please enter your Last Name',
}],
})(
<Input type="text" placeholder="Enter Your Last Name"/>
)}
</FormItem>
<FormItem label="Company Name" colon={false} style={{ marginBottom: "0px" }}>
{getFieldDecorator('Company Name', {
rules: [{
required: true, message: 'Please enter your Company Name',
}],
})(
<Input type="text" placeholder="Enter Your Company Name"/>
)}
</FormItem>
<FormItem label="Password" colon={false} style={{ marginBottom: "0px" }}>
{getFieldDecorator('password1', {
rules: [{
required: true, message: 'Please choose a password',
}, {
validator: this.validateToNextPassword,
}],
})(
<Input type="password" placeholder="Enter password"/>
)}
</FormItem>
<FormItem label="Confirm Password" colon={false} style={{ marginBottom: "0px" }}>
{getFieldDecorator('password2', {
rules: [{
required: true, message: 'Please confirm your password',
}, {
validator: this.compareToFirstPassword,
}],
})(
<Input type="password" onBlur={this.handleConfirmBlur} placeholder="Confirm password" />
)}
</FormItem>
<FormItem>
<Button type="primary" htmlType="submit" id="submitButton">Register</Button>
</FormItem>
</Form>
);
}
}
const WrappedRegistrationForm = Form.create()(RegistrationForm);
export default withRouter(WrappedRegistrationForm)
i am new to react, so please let me know if there's anything I can do to make the code easier to read or anything. I'm not sure how to create or where to put the loading spinner
You will need to implement a loading default that is displayed in your base HTML file, this is found inside your public directory as index.html.
Please refer to this answer: https://stackoverflow.com/a/60404990/2301161
Related
I am trying to implement a two-page form in React. On the first page I request a code that I use to fetch some data that I need to display on the second page. Here, by page I mean a different view on the same page. The problem that I am facing is that when I receive a response from the backend API, I use state to update the current state of the fields and this does not seem to happen immediately when I need it. When I change the value of the property that decides which view to render, the fields are still empty, not updating with the values fetched from the API. Now, I know that setState is asynchronous, but I don't know how to handle this situation, since the data fetch is done on demand, not at the beginning, so I don't think I can use useEffect for this job.
Here is my state:
const [state, setState] = useState({
name: "",
cif: "",
address: "",
phone: "",
fax: "",
managerName: "",
email: "",
password: "",
});
const [companyDataFetched, setCompanyDataFetched] = useState(false);
And here are the two views and how I switch between them:
{!companyDataFetched ? (
<CustomForm layout={theme.layout} widthelem={"70%"}>
<Form.Item
name="Company CIF:"
label="Company CIF:"
rules={[
{
pattern: new RegExp(/^\d{2,10}$/),
message: "Invalid CIF!",
},
{
required: true,
message: "Please insert the CIF of the company!",
},
]}
>
<CustomInput
backgroundcolor={theme.white}
onChange={(event) => handleChange(event, "cif")}
/>
</Form.Item>
<CustomButton
backgroundcolor={theme.primaryColor}
textcolor={theme.white}
onClick={() => {
axios.get(`${process.env.REACT_APP_API_URL}/Company/GetByCUI/${state.cif}`)
.then((res) => {
const companyInfo = res.data;
if (companyInfo.name) {
setState((prevState) => {
return {
...prevState,
name: companyInfo.name
};
});
}
if (companyInfo.address) {
setState((prevState) => {
return {
...prevState,
"address": companyInfo.address,
};
});
}
if (companyInfo.phone) {
setState((prevState) => {
return {
...prevState,
"phone": companyInfo.phone,
};
});
}
if (companyInfo.fax) {
setState((prevState) => {
return {
...prevState,
"fax": companyInfo.fax,
};
});
}
setCompanyDataFetched(true);
})
.catch((error) => {
console.log(error);
});
}}
margintop={"13%"}
marginbottom={"13%"}
>
Continue
</CustomButton>
</CustomForm>
) : (
<CustomForm layout={theme.layout} widthelem={"70%"}>
<Form.Item
name="Company name:"
label="Company name:"
rules={[
{
required: true,
message: "Please insert the name of the company!",
whitespace: true,
},
]}
>
<CustomInput
backgroundcolor={theme.white}
onChange={(event) => handleChange(event, "name")}
value={state.name}
/>
</Form.Item>
<Form.Item
name="Company CIF:"
label="Company CIF:"
rules={[
{
pattern: new RegExp(/^\d{2,10}$/),
message: "Invalid CIF!",
},
{
required: true,
message: "Please insert the CIF of the company!",
},
]}
>
<CustomInput
backgroundcolor={theme.white}
onChange={(event) => handleChange(event, "cif")}
value={state.cif}
disabled={true}
/>
</Form.Item>
<Form.Item
name="Address:"
label="Address:"
rules={[
{
required: true,
message: "Please insert the address of the company!",
whitespace: true,
},
]}
>
<CustomInput
backgroundcolor={theme.white}
onChange={(event) => handleChange(event, "address")}
value={state.address}
/>
</Form.Item>
<Form.Item
name="Phone:"
label="Phone:"
rules={[
{
required: true,
message:
"Please insert the phone number of the company!",
whitespace: true,
},
]}
>
<CustomInput
backgroundcolor={theme.white}
onChange={(event) => handleChange(event, "phone")}
value={state.phone}
/>
</Form.Item>
<Form.Item
name="Fax:"
label="Fax:"
rules={[
{
required: true,
message: "Please insert the fax of the company!",
whitespace: true,
},
]}
>
<CustomInput
backgroundcolor={theme.white}
onChange={(event) => handleChange(event, "fax")}
value={state.fax}
/>
</Form.Item>
<Form.Item
name="Manager name:"
label="Manager name:"
rules={[
{
required: true,
message:
"Please, insert the name of the company manager!",
whitespace: true,
},
]}
>
<CustomInput
backgroundcolor={theme.white}
onChange={(event) =>
handleChange(event, "managerName")
}
/>
</Form.Item>
<Form.Item
name="Manager e-mail:"
label="Manager e-mail:"
rules={[
{
type: "email",
message: "Invalid e-mail!",
},
{
required: true,
message:
"Please insert the e-mail of the company manager!",
},
]}
>
<CustomInput
backgroundcolor={theme.white}
onChange={(event) => handleChange(event, "email")}
/>
</Form.Item>
<Form.Item
name="Password:"
label="Password:"
rules={[
{
required: true,
message: "Please, insert a password!",
},
{
min: 4,
message: "Password needs to be at least 4 characters long",
},
]}
>
<CustomInput
backgroundcolor={theme.white}
onChange={(event) => handleChange(event, "password")}
type={"password"}
onKeyPress={verifyCredentials}
/>
</Form.Item>
<CustomButton
backgroundcolor={theme.primaryColor}
textcolor={theme.white}
onClick={() => {
signup();
}}
margintop={"13%"}
marginbottom={"13%"}
>
Register
</CustomButton>
</CustomForm>
)}
The major problem is that when companyDataFetched becomes true, the state containing the field values is not updated and the values of the fields don't update with the data fetched from the backend. How can I handle this issue?
[UPDATE AFTER PAIMAN'S SUGGESTION]
I tried using useEffect and another state for the API response, but the result is the same.
Here is my updated code:
useEffect(() => {
if (companyDataFetched) {
console.log(response);
setState((prevState) => {
return {
...prevState,
nume: response.name,
adresa: response.address,
telefon: response.phone,
fax: response.fax
}
});
}
}, [companyDataFetched, response]);
axios.get(`${process.env.REACT_APP_INTERNSHIP_API_URL}/Company/GetByCUI/${state.cif}`)
.then((res) => {
setResponse(res.data);
setCompanyDataFetched(true);
})
.catch((error) => {
console.log(error);
});
[UPDATE AFTER SANGEET'S SUGGESTION]
I tried using what you suggested. It did not work straight-forward, so I made some changes, but it doesn't work yet.
Here is my updated code:
useEffect(() => {
const fetchData = () => {
return axios
.get(`${process.env.REACT_APP_INTERNSHIP_API_URL}/Company/GetByCUI/${state.cif}`)
.then((res) => {
return res;
})
.catch((error) => {
console.log(error);
});
};
let isMounted = true;
if (companyDataFetched) {
(async () => {
const response = await fetchData();
if (isMounted) {
setState((prevState) => {
return {
...prevState,
name: response.data.name,
address: response.data.address,
phone: response.data.phone,
fax: response.data.fax,
};
});
} else {
setCompanyDataFetched(false);
}
})();
}
return function () {
isMounted = false;
};
}, [companyDataFetched, state.cif]);
Don't have your API call in the onClick handler. Instead trigger the fetch in the button by saying setCompanyDataFetch(true).
Then have a useEffect with companyDataFetch as a dependency.
function fetchData() {
return axios.get(`${process.env.REACT_APP_INTERNSHIP_API_URL}/Company/GetByCUI/${state.cif}`)
.then((res) => {
// setResponse(res.data);
// setCompanyDataFetched(true);
return res;
})
.catch((error) => {
console.log(error);
});
}
Your useEffect looks like so
useEffect(() => {
let isMounted = true;
if (companyDataFetched) {
(async () => {
const response = await fetchData()
if (isMounted) setState((prevState) => {
return {
...prevState,
nume: response.name,
adresa: response.address,
telefon: response.phone,
fax: response.fax
}
});
if (isMounted) setCompanyDataFetched(false);
})();
}
return function () {
isMounted = false;
};
}, [companyDataFetched]);
[UPDATED!] multi-step form implementation. pretend you get the phone number in step 1 then email in step 2.
// component.js
export default function MultiForm(){
const [step , setStep] = useState(1);
const [inputs , setInputs] = useState({
phone : '',
email : ''
});
const handleStep1 = () => {
// validation
if(inputs.phone !== ""){
// set step 2
setStep(2)
}
}
}
const handleStep2 = async() => {
// validation
if(inputs.email !== ""){
const { data , status } = await axios.post(url ,{
phone : inputs.phone,
email : inputs.email
})
if(status === 200){
alert('Registered successfully')
}
}
}
}
return (
<>
{step === 1 && (
<>
<input name="phone" onChange={(e) =>{
setInputs({...inputs , [e.target.name] : e.target.value})
}} />
<button onClick={handleStep1}>Continue</button>
</>
)}
{step === 2 && (
<input name="email" onChange={(e) =>{
setInputs({...inputs , [e.target.name] : e.target.value})
}} />
<button onClick={handleStep2}>Submit</button>
)}
</>
)
}
After a lot of research, I discovered that I was setting the input fields values in a wrong way. Apparently, when using antd Form, it must be initialized and used its reference to dynamically change Form.Item values, like so:
const [form] = Form.useForm();
const [step, setStep] = useState(1);
const [state, setState] = useState({
name: "",
cif: "",
address: "",
phone: "",
fax: "",
contactName: "",
email: "",
password: "",
});
const fetchCompanyData = async () => {
const response = await axios.get(`${process.env.REACT_APP_INTERNSHIP_API_URL}/Company/GetByCUI/${state.cif}`);
setState((prevState) => {
return {
...prevState,
nume: response.data.denumire,
adresa: response.data.adresa,
telefon: response.data.telefon,
fax: response.data.fax,
};
});
form.setFieldsValue({
nume: response.data.denumire,
cif: state.cif,
adresa: response.data.adresa,
telefon: response.data.telefon,
fax: response.data.fax,
});
setStep(2);
};
};
[...]
{step === 1 && (
<CustomForm form={form} layout={theme.layout} widthelem={"70%"}>
<Form.Item
name="Company name:"
label="Company name:"
rules={[
{
pattern: new RegExp(/^\d{2,10}$/),
message: "Invalid CIF!",
},
{
required: true,
message: "Please insert the company CIF!",
},
]}
>
<CustomInput
backgroundcolor={theme.white}
onChange={(event) => handleChange(event, "cif")}
/>
</Form.Item>
<CustomButton
backgroundcolor={theme.primaryColor}
textcolor={theme.white}
onClick={fetchCompanyData}
margintop={"13%"}
marginbottom={"13%"}
>
Continue
</CustomButton>
<CustomForm>
)}
{step === 2 && (
<CustomForm form={form} layout={theme.layout} widthelem={"70%"}>
<Form.Item
name="Company name:"
label="Company name:"
rules={[
{
required: true,
message: "Please insert the name of the company!",
whitespace: true,
},
]}
>
<CustomInput
backgroundcolor={theme.white}
onChange={(event) => handleChange(event, "name")}
/>
</Form.Item>
[...]
<CustomForm>
)}
I have a signup form inside a React functional component,
https://codesandbox.io/s/vigilant-robinson-g8y3n
The validator function returns a promise. If every field of the form is correct, it returns a resolve else a reject. If the validator returns a resolve then I perform an API Call ( Here I have just console logged "API Request Sent" ) else I console log the errors.
Even If I perform an invalid form input ( especially the email ), the API Request is still sent.
import React, { useState } from 'react';
import Button from '#material-ui/core/Button';
import { makeStyles } from '#material-ui/styles';
import TextField from '#material-ui/core/TextField';
const useStyles = makeStyles(() => ({
avatar: {
margin: '10px auto',
backgroundColor: 'green',
},
paper: {
width: '50vw',
margin: '1rem auto 3rem auto',
padding: '2rem',
display: 'flex',
flexDirection: 'column',
backgroundColor: 'blue',
backdropFilter: 'blur(10px)',
},
align: {
marginLeft: 'auto',
marginRight: 'auto',
},
field: {
width: '100%',
marginLeft: 'auto',
marginRight: 'auto',
marginTop: '15px',
},
form: {
width: '80%',
display: 'flex',
flexDirection: 'column',
margin: '1rem auto',
},
}));
export default function Signup() {
const classes = useStyles();
let [error, setError] = useState('');
let data = {};
function setData(event, key) {
data[key] = event.target.value;
}
function validator() {
console.log(data);
return new Promise((resolve, reject) => {
const exp = RegExp('w+#example.com').test(data.email);
console.log(exp);
if (!exp) {
setError('Email Not Valid! Please use Institute Email ID');
}
if (data.password !== data.password2) {
setError('Password Does Not Match!');
}
console.log(error);
if (error !== '') {
reject(error);
} else {
resolve('ok');
}
});
}
const onSignup = (e) => {
e.preventDefault();
validator()
.then(() => {
console.log('API Request Sent');
})
.catch(() => {
console.log('The errors are: '+ error)
});
};
return (
<form className={classes.form}>
<TextField
required
className={classes.field}
id="outlined-required"
label="User Name"
variant="outlined"
onChange={(event) => setData(event, 'username')}
/>
<TextField
required
type="email"
className={classes.field}
id="outlined-required"
label="Email"
variant="outlined"
onChange={(event) => {
setData(event, 'email');
}}
/>
<TextField
required
className={classes.field}
id="outlined-required"
label="First Name"
variant="outlined"
onChange={(event) => setData(event, 'first_name')}
/>
<TextField
required
className={classes.field}
id="outlined-required"
label="Last Name"
variant="outlined"
onChange={(event) => setData(event, 'last_name')}
/>
<TextField
required
type="password"
className={classes.field}
id="outlined-required"
label="Password"
variant="outlined"
onChange={(event) => setData(event, 'password')}
/>
<TextField
required
type="password"
className={classes.field}
id="outlined-required"
label="Confirm Password"
variant="outlined"
onChange={(event) => {
setData(event, 'password2');
}}
/>
<Button
className={classes.field}
color="primary"
variant="contained"
onClick={(e) => onSignup(e)}
>
Sign Up
</Button>
</form>
);
}
I ended up having to change a lot of your code. First off, you were using a plain object to handle your form state, instead of using useState.
let data = {};
function setData(event, key) {
data[key] = event.target.value;
}
I changed that to utilize useState where I also initialized all of the field values in the object right off the bat.
const [data, setDataForm] = useState({
username: "",
email: "",
first_name: "",
last_name: "",
password: "",
password2: ""
});
const setData = (e, key) => {
setDataForm((prev) => ({ ...prev, [key]: e.target.value }));
};
Not only that, you also weren't setting the value field on all of your input fields, which I added like so:
<TextField
required
className={classes.field}
id="outlined-required"
label="User Name"
variant="outlined"
onChange={(event) => setData(event, "username")}
value={data.username}
/>
For the last portion, specifically the error handling, I added a local err variable that handles recording what type of error it was. React state updates are asynchronous, and aren't guaranteed to finish before your code executes.
For example, where you do this:
if (!exp) {
setError('Email Not Valid! Please use Institute Email ID');
}
if (data.password !== data.password2) {
setError('Password Does Not Match!');
}
console.log(error);
if (error !== '') {
reject(error);
} else {
resolve('ok');
}
error might not be up to date when you attempt to reject it below. Therefore, using a local variable guarantees that you will always catch the error. At the very end you can then set the error to your error state.
Full code below (minus styles)
export default function Signup() {
const classes = useStyles();
let [error, setError] = useState("");
const [data, setDataForm] = useState({
username: "",
email: "",
first_name: "",
last_name: "",
password: "",
password2: ""
});
const setData = (e, key) => {
setDataForm((prev) => ({ ...prev, [key]: e.target.value }));
};
function validator() {
return new Promise((resolve, reject) => {
let err = "";
const exp = RegExp("w+#btech.nitdgp.ac.in|nitdgp.ac.in").test(data.email);
if (!exp) {
err = "Email Not Valid! Please use Institute Email ID";
} else if (data.password === "" || data.password !== data.password2) {
err = "Password Does Not Match!";
}
if (err !== "") {
setError(err);
reject(err);
} else {
resolve("ok");
}
});
}
const onSignup = (e) => {
e.preventDefault();
validator()
.then(() => {
console.log("API Request Sent");
})
.catch(() => {
console.log("The errors are: " + error);
});
};
return (
<form className={classes.form}>
<TextField
required
className={classes.field}
id="outlined-required"
label="User Name"
variant="outlined"
onChange={(event) => setData(event, "username")}
value={data.username}
/>
<TextField
required
type="email"
className={classes.field}
id="outlined-required"
label="Email"
variant="outlined"
onChange={(event) => {
setData(event, "email");
}}
value={data.email}
/>
<TextField
required
className={classes.field}
id="outlined-required"
label="First Name"
variant="outlined"
onChange={(event) => setData(event, "first_name")}
value={data.first_name}
/>
<TextField
required
className={classes.field}
id="outlined-required"
label="Last Name"
variant="outlined"
onChange={(event) => setData(event, "last_name")}
value={data.last_name}
/>
<TextField
required
type="password"
className={classes.field}
id="outlined-required"
label="Password"
variant="outlined"
onChange={(event) => setData(event, "password")}
value={data.password}
/>
<TextField
required
type="password"
className={classes.field}
id="outlined-required"
label="Confirm Password"
variant="outlined"
onChange={(event) => {
setData(event, "password2");
}}
value={data.password2}
/>
<Button
className={classes.field}
color="primary"
variant="contained"
onClick={(e) => onSignup(e)}
>
Sign Up
</Button>
</form>
);
}
Now I am design a password change UI in my system, I write the change passowd UI like this:
const ChangePwd = () => (
<Form
{...layout}
name='changepwd'
onFinish={onFinish}
onSubmit={this.handleSubmit}
onFinishFailed={onFinishFailed}>
<Form.Item
label='old password'
name='oldpassword'
rules={[
{
required: true,
message: 'Please input your username!'
}
]}>
<Input />
</Form.Item>
<Form.Item
label='new password'
name='newpassword'
rules={[
{
required: true,
message: 'Please input your password!'
}
]}>
<Input.Password />
</Form.Item>
<Form.Item
label='repeat pasword'
name='newpasswordrepeat'
rules={[
{
required: true,
message: 'Please input your password!'
}
]}>
<Input.Password />
</Form.Item>
<Form.Item {...tailLayout}>
<Button type='primary' htmlType='submit'>
submit
</Button>
</Form.Item>
</Form>
)
I want to get the value of password and send to backend, what should I get the value of the user input? Now I am doing it like this but could not get the value of user input:
handleSubmit = (values) => {
let { oldpassword, newpassword } = values
if (newpassword !== oldpassword) {
alert('new password not equal to old')
return
}
let user = localStorage.getItem("user");
var request = {
phone: user.phone,
oldPassword: oldpassword,
newPassword: newpassword
}
modifyPassword(request)
}
use the onchange event:
<Input.Password value={this.state.oldPassword} onChange={this.handleOldPasswordChange} />
and get the user input like this:
handleOldPasswordChange = e => {
if (this.state.oldPassword !== e.target.value) {
this.setState({
oldPassword: e.target.value
})
}
}
works.
this may not be able to be answered, but I am going to try to include as much detail as possible. I have this page called registrationForm.js, which in my routes.js is set to render with the path /signup. It does render the page, but it is blank. When I refresh the page, for a split second I see all the elements I'm supposed to, the input fields, the buttons, the images. But for some reason, it goes back to being fully white page.
Here is the entire registrationForm.js code!
import React from 'react'
import './RegistrationForm.css'
import { Alert, Button, Form, Input } from 'antd'
import { AuthorizationHome } from '../models'
import { withRouter } from 'react-router-dom'
import * as routes from '../routes'
import facades from '../facades'
import firebase from 'firebase'
import { useState } from "react";
import {createCheckoutSession} from '../Stripepayment/checkout'
let firestore = firebase.firestore()
const FormItem = Form.Item
// const [firstname, setFirstName] = useState("");
// const [lastname, setLastName] = useState("");
// const [companyname, setCompanyName] = useState("");
// const [accountStatus, setAccountStatus] = useState("");
var userIDStripeSubmit = ""
class RegistrationForm extends React.Component {
state = {
confirmDirty: false,
}
onSubmit = (event) => {
event.preventDefault();
this.props.form.validateFields((err, values) => {
if (err) return
const email = this.props.form.getFieldValue('email')
const passwordOne = this.props.form.getFieldValue('password1')
const firstName = this.props.form.getFieldValue('First Name')
const lastName = this.props.form.getFieldValue('Last Name')
const companyName = this.props.form.getFieldValue('Company Name')
const {
history,
} = this.props
AuthorizationHome.doCreateUserWithEmailAndPassword(email, passwordOne)
.then((authUser) => facades.userFacade().doCreateUser(authUser.user.uid, email))
// .then((authUser) => {
// history.push(createCheckoutSession(authUser.user.uid))
// })
.catch(error => {
this.setState({'error': error})
})
// adding into profiledata collection
// var userID = ""
firebase.auth().onAuthStateChanged((user) => {
if(user) {
// console.log("profile.js " + user.uid)
// userID = user.uid
// userID = user.uid
console.log(user.uid)
userIDStripeSubmit = user.uid
console.log("userid inside firebase auth is" + user.uid)
// var firstNameFromField =
// console.log("this props : " + this.props.form.getFieldValue('First Name'))
firestore.collection('profiledata').doc(user.uid).set({
firstname: firstName,
lastname: lastName,
companyname: companyName,
accountStatus: "inactive",
})
.catch(error => {
alert(error.message);
});
createCheckoutSession(user.uid)
}
})
// firestore collection query
// setFirstName("");
// setLastName("");
// setCompanyName("");
// setAccountStatus("")
})
}
handleConfirmBlur = (e) => {
const value = e.target.value;
this.setState({ confirmDirty: this.state.confirmDirty || !!value });
}
compareToFirstPassword = (rule, value, callback) => {
const form = this.props.form;
if (value && value !== form.getFieldValue('password1')) {
callback('Passwords do not match!');
} else {
callback();
}
}
validateToNextPassword = (rule, value, callback) => {
const form = this.props.form;
if (value && this.state.confirmDirty) {
form.validateFields(['password2'], { force: true });
}
callback();
}
render() {
const { getFieldDecorator } = this.props.form
const { error } = this.state
return (
<Form onSubmit={this.onSubmit} hideRequiredMark={true} className="registration-form" style={{ marginBottom: "0px" }}>
{ error && <Alert type="error" message={error.message}/> }
<FormItem label="Email" colon={false} style={{ marginBottom: "0px" }}>
{getFieldDecorator('email', {
rules: [{
type: 'email', message: 'Invalid email address',
}, {
required: true, message: 'Please input your email address',
}],
})(
<Input placeholder="Enter email" />
)}
</FormItem>
{/* */}
<FormItem label="First Name" colon={false} style={{ marginBottom: "0px" }}>
{getFieldDecorator('First Name', {
rules: [{
required: true, message: 'Please enter your First Name',
}],
})(
<Input type="text" placeholder="Enter Your First Name"/>
)}
</FormItem>
<FormItem label="Last Name" colon={false} style={{ marginBottom: "0px" }}>
{getFieldDecorator('Last Name', {
rules: [{
required: true, message: 'Please enter your Last Name',
}],
})(
<Input type="text" placeholder="Enter Your Last Name"/>
)}
</FormItem>
<FormItem label="Company Name" colon={false} style={{ marginBottom: "0px" }}>
{getFieldDecorator('Company Name', {
rules: [{
required: true, message: 'Please enter your Company Name',
}],
})(
<Input type="text" placeholder="Enter Your Company Name"/>
)}
</FormItem>
<FormItem label="Password" colon={false} style={{ marginBottom: "0px" }}>
{getFieldDecorator('password1', {
rules: [{
required: true, message: 'Please choose a password',
}, {
validator: this.validateToNextPassword,
}],
})(
<Input type="password" placeholder="Enter password"/>
)}
</FormItem>
<FormItem label="Confirm Password" colon={false} style={{ marginBottom: "0px" }}>
{getFieldDecorator('password2', {
rules: [{
required: true, message: 'Please confirm your password',
}, {
validator: this.compareToFirstPassword,
}],
})(
<Input type="password" onBlur={this.handleConfirmBlur} placeholder="Confirm password" />
)}
</FormItem>
{/* inserting into profiledata collection firestore */}
{/* ending profiledata collection insert firestore */}
{/*
<FormItem label="First Name" colon={false} >
<Input placeholder = "Enter Your First Name" style={{ maxWidth: '100%', maxHeight: '50%' , }}
value = { firstname }
onChange = {
(e) => setFirstName(e.target.value)
}/>
</FormItem>
<FormItem label="Last Name" colon={false}>
<Input placeholder = "Enter Your Last Name" style={{ maxWidth: '100%', maxHeight: '50%' }}
value = { lastname }
onChange = {
(e) => setLastName(e.target.value)
}/>
</FormItem>
<FormItem label="Company Name" colon={false}> <
Input placeholder = "Enter Your Company name." style={{ maxWidth: '100%', maxHeight: '50%' }}
value = { companyname }
onChange = {
(e) => setCompanyName(e.target.value)
}
/ >
</FormItem> */}
<FormItem>
<Button type="primary" htmlType="submit" id="submitButton">Register</Button>
</FormItem>
</Form>
);
}
}
const WrappedRegistrationForm = Form.create()(RegistrationForm);
export default withRouter(WrappedRegistrationForm)
am I missing something to actually render the elements on page?! All my other pages are rendering fine, just not this one! Any suggestions?
I am making a different form component using ant design and trying to bind several different inputs
Here is the code :
this.state = {
title: '',
product: '',
options: 0,
price: 0,
}
onTitleChange = (e) => {
this.setState({
title: e.target.value
})
}
onProductChange = (e) => {
this.setState({
product: e.target.value
})
}
onHandleChange = value => {
this.setState({
priceOption: value
})
}
onNumberChange = e => {
this.setState({
price: e.target.value
})
}
<FormItemRow>
<Col span={24} style={colStyle}>
<FormItem label={'title'} colon={false} style={{ marginBottom: 0 }}>
{getFieldDecorator('title', {
rules: [
{ required: true, message: 'title is required' },
],
})(<Input onChange={this.onTitleChange}/>)}
</FormItem>
</Col>
</FormItemRow>
<FormItemRow>
<Col span={24} style={colStyle}>
<FormItem label={'product-number'} colon={false} style={{ marginBottom: 0 }}>
{getFieldDecorator('product-number', {
rules: [{ required: true, message: 'product-number is required' }],
})(<Input onChange={this.onProductChange}/>)}
</FormItem>
</Col>
</FormItemRow>
<FormItemRow>
<Col span={12} style={colStyle}>
<FormItem label={'options'} colon={false} style={{ marginBottom: 0 }}>
{getFieldDecorator('options', {
rules: [
{ required: true, message: 'options is required' },
],
})(<Select onChange={this.onHandleChange}>{this.handWashOptions(this.props.handWashOptions)}</Select>)}
</FormItem>
</Col>
<Col span={12} style={colStyle}>
<FormItem label={'price'} colon={false} style={{ marginBottom: 0 }}>
{getFieldDecorator('price', {
rules: [
{ required: true, message: 'price is required' },
],
})(<Input type="number" onChange={this.onNumberChange}/>)}
</FormItem>
</Col>
</FormItemRow>
title and product using just Input component.
option is using Select component.
and price is using Input type number component.
I think it is very inefficient using different onChange callback on each input component.
Is there any way I can bind one onChange callback function?
You can simply make a generic function handleChange, pass the name and value which are to be updated
handleChange(name,value){
this.setState({[name]: value})
}
and pass value to handle change like this
<Input onChange={(name,value)=>this.onTitleChange(name,value)}/>
You can use e.target.value to get value from target, also if you need to have different logic for some particular element then you can simply add a exception in handleChange
this.state = {
fields:{
each:
field:
you:
have:
}
}
handleChange = (event) => {
const { value, type, name } = event.currentTarget
console.log(type, value, name);
this.setState(prevState => ({
fields: {
...prevState.fields,
[name]: type === 'number' ? parseInt(value, 10) : value
}
}));
};
As stated in Handling Multiple Inputs,
add a name attribute to each element and let the handler function choose what to do based on the value of event.target.name.
So you can have:
onChange = event => {
const name = event.target.name;
this.setState({
[name]: event.target.value
})
}
// Add `name` attribute used for event.target.name
<Select onChange={this.onChange} name="wash">...</Select>
<Input type="number" onChange={this.onChange} name="number"/>
<Input onChange={this.onChange} name="product" />