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?
Related
Warning: A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component.
I am creating a Social Media App and facing this problems, what is wrong in my code?
Following is my code:
import { useState } from "react";
import {
Box,
Button,
TextField,
useMediaQuery,
Typography,
useTheme,
} from "#mui/material";
import EditOutlinedIcon from "#mui/icons-material/EditOutlined";
import { Formik } from "formik";
import * as yup from "yup";
import { useNavigate } from "react-router-dom";
import { useDispatch } from "react-redux";
import { setLogin } from "state";
import Dropzone from "react-dropzone";
import FlexBetween from "components/FlexBetween";
const registerSchema = yup.object().shape({
firstName: yup.string().required("required"),
lastName: yup.string().required("required"),
email: yup.string().email("invalid email").required("required"),
password: yup.string().required("required"),
location: yup.string().required("required"),
occupation: yup.string().required("required"),
picture: yup.string().required("required"),
});
const loginSchema = yup.object().shape({
email: yup.string().email("invalid email").required("required"),
password: yup.string().required("required"),
});
const initialValuesRegister = {
firstName: "",
lastName: "",
email: "",
password: "",
location: "",
occupation: "",
picture: "",
};
const initialValuesLogin = {
email: "",
password: "",
};
const Form = () => {
const [pageType, setPageType] = useState("login");
const { palette } = useTheme();
const dispatch = useDispatch();
const navigate = useNavigate();
const isNonMobile = useMediaQuery("(min-width:600px)");
const isLogin = pageType === "login";
const isRegister = pageType === "register";
const register = async (values, onSubmitProps) => {
// this allows us to send form info with image
const formData = new FormData();
for (let value in values) {
formData.append(value, values[value]);
}
formData.append("picturePath", values.picture.name);
const savedUserResponse = await fetch(
"http://localhost:3001/auth/register",
{
method: "POST",
body: formData,
}
);
const savedUser = await savedUserResponse.json();
onSubmitProps.resetForm();
if (savedUser) {
setPageType("login");
}
};
const login = async (values, onSubmitProps) => {
const loggedInResponse = await fetch("http://localhost:3001/auth/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(values),
});
const loggedIn = await loggedInResponse.json();
onSubmitProps.resetForm();
if (loggedIn) {
dispatch(
setLogin({
user: loggedIn.user,
token: loggedIn.token,
})
);
navigate("/home");
}
};
const handleFormSubmit = async (values, onSubmitProps) => {
if (isLogin) await login(values, onSubmitProps);
if (isRegister) await register(values, onSubmitProps);
};
return (
<Formik
onSubmit={handleFormSubmit}
initialValues={isLogin ? initialValuesLogin : initialValuesRegister}
validationSchema={isLogin ? loginSchema : registerSchema}
>
{({
values,
errors,
touched,
handleBlur,
handleChange,
handleSubmit,
setFieldValue,
resetForm,
}) => (
<form onSubmit={handleSubmit}>
<Box
display="grid"
gap="30px"
gridTemplateColumns="repeat(4, minmax(0, 1fr))"
sx={{
"& > div": { gridColumn: isNonMobile ? undefined : "span 4" },
}}
>
{isRegister && (
<>
<TextField
label="First Name"
onBlur={handleBlur}
onChange={handleChange}
value={values.firstName}
name="firstName"
error={
Boolean(touched.firstName) && Boolean(errors.firstName)
}
helperText={touched.firstName && errors.firstName}
sx={{ gridColumn: "span 2" }}
/>
<TextField
label="Last Name"
onBlur={handleBlur}
onChange={handleChange}
value={values.lastName}
name="lastName"
error={Boolean(touched.lastName) && Boolean(errors.lastName)}
helperText={touched.lastName && errors.lastName}
sx={{ gridColumn: "span 2" }}
/>
<TextField
label="Location"
onBlur={handleBlur}
onChange={handleChange}
value={values.location}
name="location"
error={Boolean(touched.location) && Boolean(errors.location)}
helperText={touched.location && errors.location}
sx={{ gridColumn: "span 4" }}
/>
<TextField
label="Occupation"
onBlur={handleBlur}
onChange={handleChange}
value={values.occupation}
name="occupation"
error={
Boolean(touched.occupation) && Boolean(errors.occupation)
}
helperText={touched.occupation && errors.occupation}
sx={{ gridColumn: "span 4" }}
/>
<Box
gridColumn="span 4"
border={`1px solid ${palette.neutral.medium}`}
borderRadius="5px"
p="1rem"
>
<Dropzone
acceptedFiles=".jpg,.jpeg,.png"
multiple={false}
onDrop={(acceptedFiles) =>
setFieldValue("picture", acceptedFiles[0])
}
>
{({ getRootProps, getInputProps }) => (
<Box
{...getRootProps()}
border={`2px dashed ${palette.primary.main}`}
p="1rem"
sx={{ "&:hover": { cursor: "pointer" } }}
>
<input {...getInputProps()} />
{!values.picture ? (
<p>Add Picture Here</p>
) : (
<FlexBetween>
<Typography>{values.picture.name}</Typography>
<EditOutlinedIcon />
</FlexBetween>
)}
</Box>
)}
</Dropzone>
</Box>
</>
)}
<TextField
label="Email"
onBlur={handleBlur}
onChange={handleChange}
value={values.email}
name="email"
error={Boolean(touched.email) && Boolean(errors.email)}
helperText={touched.email && errors.email}
sx={{ gridColumn: "span 4" }}
/>
<TextField
label="Password"
type="password"
onBlur={handleBlur}
onChange={handleChange}
value={values.password}
name="password"
error={Boolean(touched.password) && Boolean(errors.password)}
helperText={touched.password && errors.password}
sx={{ gridColumn: "span 4" }}
/>
</Box>
{/* BUTTONS */}
<Box>
<Button
fullWidth
type="submit"
sx={{
m: "2rem 0",
p: "1rem",
backgroundColor: palette.primary.main,
color: palette.background.alt,
"&:hover": { color: palette.primary.main },
}}
>
{isLogin ? "LOGIN" : "REGISTER"}
</Button>
<Typography
onClick={() => {
setPageType(isLogin ? "register" : "login");
resetForm();
}}
sx={{
textDecoration: "underline",
color: palette.primary.main,
"&:hover": {
cursor: "pointer",
color: palette.primary.light,
},
}}
>
{isLogin
? "Don't have an account? Sign Up here."
: "Already have an account? Login here."}
</Typography>
</Box>
</form>
)}
</Formik>
);
};
export default Form;
The file upload input is changing from undefined to defined (thus changing it from uncontrolled to controlled which is not good practice in react) since it has no initial value. I haven't used formik alot but you should read through the docs and check how to set initial value for a dropzone.
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>
);
}
I am unable to get the values of email and password from the FormControl Input values. I am using the BaseWeb ReactUI framework for the field UI.
Need help stuck on this issue.
import { FormControl } from 'baseui/form-control';
import { Input } from 'baseui/input';
import { useStyletron } from 'baseui';
import { Alert } from 'baseui/icon';
import { Button } from 'baseui/button';
import { TiUserAddOutline } from "react-icons/ti";
import Axios from "axios";
import { useHistory, Link } from 'react-router-dom';
import { validate as validateEmail } from 'email-validator'; // add this package to your repo with `$ yarn add email-validator`
import { Select } from 'baseui/select';
import { Checkbox } from 'baseui/checkbox';
function SelectAtStart(props) {
const [css] = useStyletron();
return (
<div className={css({ display: 'flex' })}>
<div className={css({ width: '200px', paddingRight: '8px' })}>
<Select
options={props.options}
labelKey="id"
valueKey="gender"
onChange={({ value }) => props.onSelectChange(value)}
value={props.selectValue}
id={props.id}
/>
</div>
<Input
onChange={e => props.onInputChange(e.target.value)}
value={props.inputValue}
/>
</div>
);
}
function Negative() {
const [css, theme] = useStyletron();
return (
<div
className={css({
display: 'flex',
alignItems: 'center',
paddingRight: theme.sizing.scale500,
color: theme.colors.negative400,
})}
>
<Alert size="18px" />
</div>
);
}
export function RegisterFields() {
const history = useHistory();
const [css, theme] = useStyletron();
const [email, setEmail] = React.useState('');
const [password, setPassword] = React.useState('');
const [checked, setChecked] = React.useState(true);
const [startInputValue, setStartInputValue] = React.useState('');
const [startSelectValue, setStartSelectValue] = React.useState(
[],
);
const [isValid, setIsValid] = React.useState(false);
const [isVisited, setIsVisited] = React.useState(false);
const shouldShowError = !isValid && isVisited;
const onChangeEmail = ({ target: { email } }) => {
setIsValid(validateEmail(email));
setEmail(email);
};
const onChangePassword = ({ target: { password } }) => {
setIsValid(true);
setPassword(password);
}
const handleSubmit = (event) => {
event.preventDefault();
console.log(email, password)
Axios.defaults.headers.common = {
"Content-Type": "application/json"
}
Axios.post("http://localhost:5000/api/signup", {
email: email,
password: password,
firstName: startInputValue,
lastname: startInputValue,
agreement: checked
}).then((res) => {
if (res.status === 200) {
const path = '/dashboard'
history.push(path)
console.log(res)
}
else {
console.log("Unable to create account")
}
})
}
return (
<form
onSubmit={handleSubmit}
className={css({
marginTop: theme.sizing.scale1000,
})}
>
<FormControl
label="Your Email"
error={
shouldShowError
? 'Please input a valid email address'
: null
}
>
<Input
id="email"
value={email}
onChange={onChangeEmail}
onBlur={() => setIsVisited(true)}
error={shouldShowError}
overrides={shouldShowError ? { After: Negative } : {}}
type="email"
required
/>
</FormControl>
<FormControl
label="Your Password"
error={
shouldShowError
? 'Your password is incorrect'
: null
}
>
<Input
id="password"
value={password}
onChange={onChangePassword}
onBlur={() => setIsVisited(true)}
error={shouldShowError}
overrides={shouldShowError ? { After: Negative } : {}}
type="password"
required
/>
</FormControl>
<FormControl
label="Your Full Name"
>
<SelectAtStart
inputValue={startInputValue}
onInputChange={v => setStartInputValue(v)}
selectValue={startSelectValue}
onSelectChange={v => setStartSelectValue(v)}
options={[
{ id: 'Mr', gender: 'Male' },
{ id: 'Mrs', gender: 'Women' },
{ id: 'Ms', gender: 'Female' },
{ id: 'None', gender: 'Dont Say' },
]}
id="start-id"
/>
</FormControl>
<FormControl>
<Checkbox
checked={checked}
onChange={() => setChecked(!checked)}
>
<div className={css({
color:'grey'
})}
>I hereby agree to the terms and conditons of the platform.</div>
</Checkbox>
</FormControl>
<Button type="submit">
<TiUserAddOutline style={{ marginRight: '10px' }} />
Create Account
</Button>
<div>
<p style={{ marginTop: '10px', color: 'grey' }} >To go back to login, please <Link to='/'>click here</Link></p>
</div>
</form>
);
}
I believe it's because you keep setting it to the email/password value of target
which is "undefined".
e.target.email = undefined
e.target.password = undefined
Try with this approach:
const onChangeEmail = e =>
{
setIsValid(validateEmail(e.target.value));
setEmail(e.target.value);
};
const onChangePassword = e =>
{
setIsValid(true);
setEmail(e.target.value);
};
Here you can see that all text inputs are stored in a value of targeted event ( event.target.value )
I am setting the selectedType variable and opening ant design Modal containing ant design Form with initialValues filled with selectedType.
But the initialValues in the form are only working for the first time I click on Edit button and if I close the Modal and click on Edit button for a different selectedType the Modal shows the values of first time selected selectedType.
I have used destroyOnClose={true} for Modal to fetch the new value of selectedType but it doesn't solve the issue.
Here's my code:
import {
Button, Form,
Input,Table,
Modal
} from "antd";
import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
const ManageTypeScreen = () => {
const dispatch = useDispatch();
const productTypeList = useSelector(state => state.productTypeList);
const [editForm] = Form.useForm();
const [selectedType, setselectedType] = useState({});
const [showEditModal, setshowEditModal] = useState(false);
useEffect(() => {
getProductTypeList(dispatch);
}, [])
const handleEditClose = () => {
setshowEditModal(false);
};
const handleEditShow = (val) => {
console.log(val);
setselectedType(val);
setshowEditModal(true);
};
const columns = [
{
title: 'Type Name',
dataIndex: 'name',
key: 'name'
},
{
title: 'Short Cut',
dataIndex: 'shortCut',
key: 'shortCut'
},
{
title: 'Edit',
sortable: false,
filterable: false,
render: (text, pro) => (
<div>
<Button type="primary" size="sm block" onClick={() => handleEditShow(pro)}>
Edit
</Button>
</div>)
},
];
return (
{selectedType !== undefined &&
<Modal
title="Edit Type"
visible={showEditModal}
onCancel={handleEditClose}
destroyOnClose={true}
footer={null}
centered={true}
>
<Form
labelCol={{ span: 9 }}
wrapperCol={{ span: 12 }}
layout="horizontal"
form={editForm}
requiredMark={true}
initialValues={selectedType}
size="medium"
>
<Form.Item
label="Type Name:"
name="name"
rules={[
{ required: true, message: "Please input Name!" }
]}>
<Input maxLength={32} />
</Form.Item>
<Form.Item
label="ShortCut"
name="shortCut"
rules={[
{
required: true,
message: "Please input ShortCut!"
}
]}>
<Input maxLength={3} />
</Form.Item>
< Form.Item
wrapperCol={{
span: 5,
offset: 7
}}
style={{ marginTop: "35px" }}
>
<Button
type="primary"
htmlType="submit"
size="large"
loading={editLoading}
>
Update Type
</Button>
</Form.Item>
</Form>
</Modal>
}
{
productTypeList !== undefined &&
<div style={{ marginLeft: "30px", marginRight: "30px" }}>
<Table
className="product-type-list-table"
columns={columns}
pagination={false}
dataSource={productTypeList}
rowKey={record => record.id}
/>
</div>
}
</div >
)
}
I don't know if it's the solution, but I'd suggest not messing up the rendering of the modal with both conditional rendering and a visible prop, it makes it hard to track.
Try something like
visible={selectedType !== undefined && showEditModal}
Or better yet, just get rid of the showEditModal variable since you're always changing it in accord with selectedType.
I think you can do it by changing you close function to
const handleEditClose = () => {
setshowEditModal(null);
};
Set the initial value of selectedType to null
and your modal's props to
<Modal
title="Edit Type"
visible={!!selectedType}
(Though it might give you an error because it might try to render the modal when selectedType is null, then just switch back to conditional rendering and set the visible prop to be always true)
import {
Button, Form,
Input,Table,
Modal
} from "antd";
import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
const ManageTypeScreen = () => {
const dispatch = useDispatch();
const productTypeList = useSelector(state => state.productTypeList);
const [editForm] = Form.useForm();
const [selectedType, setselectedType] = useState({});
const [showEditModal, setshowEditModal] = useState(false);
useEffect(() => {
getProductTypeList(dispatch);
}, [])
const handleEditClose = () => {
setshowEditModal(false);
};
const handleEditShow = (val) => {
console.log(val);
setselectedType(val);
setshowEditModal(true);
};
const columns = [
{
title: 'Type Name',
dataIndex: 'name',
key: 'name'
},
{
title: 'Short Cut',
dataIndex: 'shortCut',
key: 'shortCut'
},
{
title: 'Edit',
sortable: false,
filterable: false,
render: (text, pro) => (
<div>
<Button type="primary" size="sm block" onClick={() => handleEditShow(pro)}>
Edit
</Button>
</div>)
},
];
return (
{selectedType !== undefined &&
<Modal
title="Edit Type"
visible={showEditModal}
onCancel={handleEditClose}
destroyOnClose={true}
footer={null}
centered={true}
>
<Form
labelCol={{ span: 9 }}
wrapperCol={{ span: 12 }}
layout="horizontal"
form={editForm}
requiredMark={true}
size="medium"
>
<Form.Item
label="Type Name:"
name="name"
initialValue={selectedType.name}
preserve={false}
rules={[
{ required: true, message: "Please input Name!" }
]}>
<Input maxLength={32} />
</Form.Item>
<Form.Item
label="ShortCut"
name="shortCut"
initialValue={selectedType.shortCut}
preserve={false}
rules={[
{
required: true,
message: "Please input ShortCut!"
}
]}>
<Input maxLength={3} />
</Form.Item>
< Form.Item
wrapperCol={{
span: 5,
offset: 7
}}
style={{ marginTop: "35px" }}
>
<Button
type="primary"
htmlType="submit"
size="large"
loading={editLoading}
>
Update Type
</Button>
</Form.Item>
</Form>
</Modal>
}
{
productTypeList !== undefined &&
<div style={{ marginLeft: "30px", marginRight: "30px" }}>
<Table
className="product-type-list-table"
columns={columns}
pagination={false}
dataSource={productTypeList}
rowKey={record => record.id}
/>
</div>
}
</div >
)
}
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