How to do internal redirecting in reactjs? - javascript

I'm kinda new to react and was wondering how to internally redirect your pages in reactjs. I have two pages called register and register2. In register page, I just check if the email exists in the database or not and if it doesn't exist then it redirects to register2 page for creating the full account with username and password. However, in the address bar, it kinda looks ugly to show something like register2. So I was wondering if there is any way through which I can internally redirect without changing the address in the address bar to register2 such that it stays as register throughout the whole account creation process.
I created a codesandbox to show the issue
register.js
import React, { useState } from "react";
import { Formik } from "formik";
import TextField from "#material-ui/core/TextField";
import * as Yup from "yup";
import Avatar from "#material-ui/core/Avatar";
import Button from "#material-ui/core/Button";
import CssBaseline from "#material-ui/core/CssBaseline";
import Link from "#material-ui/core/Link";
import Grid from "#material-ui/core/Grid";
import Box from "#material-ui/core/Box";
import LockOutlinedIcon from "#material-ui/icons/LockOutlined";
import Typography from "#material-ui/core/Typography";
import { makeStyles } from "#material-ui/core/styles";
import Container from "#material-ui/core/Container";
function Copyright() {
return (
<Typography variant="body2" color="textSecondary" align="center">
<Link color="inherit" href="sad">
New1
</Link>{" "}
{new Date().getFullYear()}
{"."}
</Typography>
);
}
const useStyles = makeStyles(theme => ({
paper: {
marginTop: theme.spacing(8),
display: "flex",
flexDirection: "column",
alignItems: "center"
},
avatar: {
margin: theme.spacing(1),
backgroundColor: theme.palette.secondary.main
},
form: {
width: "100%",
marginTop: theme.spacing(1)
},
submit: {
margin: theme.spacing(3, 0, 2)
}
}));
const Reg = props => {
const classes = useStyles();
const [loginError, setLoginError] = useState("");
const [changed, setChanged] = useState(false);
const [newpage, setNew] = useState(false);
const handleSubmit = async (values, { setSubmitting }) => {
const { email } = values;
var body = {
email: email
};
console.log(body);
const options = {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json"
},
body: JSON.stringify(body)
};
const url = "/api/emailcheck";
try {
const response = await fetch(url, options);
const text = await response.text();
setSubmitting(false);
setChanged(false);
setNew(true);
console.log(text);
if (newpage) {
props.history.push({
pathname: "/register2",
state: { email }
});
// props.history.push(`/register2/${email}`);
} else if (text === "exists") {
props.history.push(`/`);
} else {
setLoginError("Email is invalid");
}
} catch (error) {
console.error(error);
}
};
return (
<Formik
initialValues={{ email: "" }}
onSubmit={handleSubmit}
//********Using Yup for validation********/
validationSchema={Yup.object().shape({
email: Yup.string()
.email()
.required("Required")
})}
>
{props => {
const {
values,
touched,
errors,
isSubmitting,
handleChange,
handleBlur,
handleSubmit
} = props;
return (
<>
<Container component="main" maxWidth="xs">
<CssBaseline />
<div className={classes.paper}>
<Avatar className={classes.avatar}>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
Sign in
</Typography>
<form
className={classes.form}
onSubmit={handleSubmit}
noValidate
>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="email"
value={values.email}
label="Email Address"
name="email"
autoComplete="email"
onChange={e => {
setChanged(true);
handleChange(e);
}}
onBlur={handleBlur}
className={errors.email && touched.email && "error"}
/>
{errors.email && touched.email && (
<div className="input-feedback" style={{ color: "red" }}>
{errors.email}
</div>
)}
{!changed && loginError && (
<div style={{ color: "red" }}>
<span>{loginError}</span>
</div>
)}
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
className={classes.submit}
disabled={isSubmitting}
>
Next
</Button>
<Grid container justify="flex-end">
<Grid item>
<Link href="/" variant="body2">
Already have an account? Sign in
</Link>
</Grid>
</Grid>
</form>
</div>
<Box mt={5}>
<Copyright />
</Box>
</Container>
</>
);
}}
</Formik>
);
};
export default Reg;
register2.js
import React, { useState } from "react";
import { Formik } from "formik";
import TextField from "#material-ui/core/TextField";
import { withRouter, useHistory } from "react-router-dom";
import * as Yup from "yup";
import Avatar from "#material-ui/core/Avatar";
import Button from "#material-ui/core/Button";
import CssBaseline from "#material-ui/core/CssBaseline";
import Link from "#material-ui/core/Link";
import Box from "#material-ui/core/Box";
import LockOutlinedIcon from "#material-ui/icons/LockOutlined";
import Typography from "#material-ui/core/Typography";
import { makeStyles } from "#material-ui/core/styles";
import Container from "#material-ui/core/Container";
function Copyright() {
return (
<Typography va riant="body2" color="textSecondary" align="center">
<Link color="inherit" href="sad">
New
</Link>{" "}
{new Date().getFullYear()}
{"."}
</Typography>
);
}
const useStyles = makeStyles(theme => ({
paper: {
marginTop: theme.spacing(8),
display: "flex",
flexDirection: "column",
alignItems: "center"
},
avatar: {
margin: theme.spacing(1),
backgroundColor: theme.palette.secondary.main
},
form: {
width: "100%",
marginTop: theme.spacing(1)
},
submit: {
margin: theme.spacing(3, 0, 2)
}
}));
const Reg2 = props => {
const classes = useStyles();
const [loginError, setLoginError] = useState("");
const history = useHistory();
const [changed, setChanged] = useState(false);
const handleSubmit = async (values, { setSubmitting }) => {
const { username, password } = values;
var body = {
username: username,
password: password,
email: history.location.state.email
};
console.log(body);
const options = {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json"
},
body: JSON.stringify(body)
};
const url = "/api/register";
try {
const response = await fetch(url, options);
const text = await response.text();
setSubmitting(false);
setChanged(false);
console.log(text);
if (text === "verifyemail") {
props.history.push({
pathname: "/verifyOtp",
state: { email: body.email }
});
// props.history.push(`/verifyOtp/${username}`);
} else {
setLoginError("Username or Password is incorrect");
}
} catch (error) {
console.error(error);
}
};
return (
<Formik
initialValues={{ username: "", password: "", confirmPassword: "" }}
onSubmit={handleSubmit}
//********Using Yup for validation********/
validationSchema={Yup.object().shape({
username: Yup.string().required("Required"),
password: Yup.string()
.required("No password provided.")
.min(8, "Password is too short - should be 8 chars minimum.")
.matches(/(?=.*[0-9])/, "Password must contain a number.")
.matches(
/(?=.*[●!"#$%&'()*+,\-./:;<=>?#[\\\]^_`{|}~])/,
"Password must contain a symbol."
),
confirmPassword: Yup.string()
.required("Enter to confirm password")
.oneOf([Yup.ref("password"), null], "Password do not match")
})}
>
{props => {
const {
values,
touched,
errors,
isSubmitting,
handleChange,
handleBlur,
handleSubmit
} = props;
return (
<>
<Container component="main" maxWidth="xs">
<CssBaseline />
<div className={classes.paper}>
<Avatar className={classes.avatar}>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
Enter Info
</Typography>
<form
className={classes.form}
onSubmit={handleSubmit}
noValidate
>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="username"
value={values.username}
label="username"
name="username"
autoComplete="username"
onChange={e => {
setChanged(true);
handleChange(e);
}}
onBlur={handleBlur}
className={errors.username && touched.username && "error"}
/>
{errors.username && touched.username && (
<div className="input-feedback" style={{ color: "red" }}>
{errors.username}
</div>
)}
<TextField
variant="outlined"
margin="normal"
required
fullWidth
name="password"
value={values.password}
label="Password"
type="password"
id="password"
onBlur={handleBlur}
autoComplete="current-password"
className={errors.password && touched.password && "error"}
onChange={e => {
setChanged(true);
handleChange(e);
}}
/>
{errors.password && touched.password && (
<div className="input-feedback" style={{ color: "red" }}>
{errors.password}
</div>
)}
<TextField
variant="outlined"
margin="normal"
required
fullWidth
name="confirmPassword"
value={values.confirmPassword}
type="password"
label="Confirm Password"
id="confirmPassword"
onBlur={handleBlur}
autoComplete="confirmPassword"
className={
errors.confirmPassword &&
touched.confirmPassword &&
"error"
}
onChange={e => {
setChanged(true);
handleChange(e);
}}
/>
{errors.confirmPassword && touched.confirmPassword && (
<div className="input-feedback" style={{ color: "red" }}>
{errors.confirmPassword}
</div>
)}
{!changed && loginError && (
<div style={{ color: "red" }}>
<span>{loginError}</span>
</div>
)}
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
className={classes.submit}
disabled={isSubmitting}
>
Next
</Button>
</form>
</div>
<Box mt={8}>
<Copyright />
</Box>
</Container>
</>
);
}}
</Formik>
);
};
export default withRouter(Reg2);

you could make a parent component for register and register2 and store your logic there in which component to display
function MyComponent() {
const [email, setEmail] = useState(null)
useEffect(() => {
(async () => {
const response = await yourApiCall()
setEmail(response)
})()
}, [])
return email ? <Register /> : <Register2 />
}

Initially show the register component or code of that sort.
Call an api, if the email exists, store flag value in that and do conditional rendering for another component or code of register2.
Initially, this.state.isEmailExist : false,
After api call change flag value accordingly. If true then render Register2.
const contents = if (!this.state.isEmailExist) {
return (
<Register />
);
} else {
return (
<Register2 />
)
}
return(
<div>{contents}</div>
)

Maybe you are looking for this
window.open("https://www.youraddress.com","_self");
Make sure to setup the validation.

Related

Warning: Failed prop type: The prop `open` is marked as required in `ForwardRef(Modal)`, but its value is `undefined`

I get a warning after applying code from Material UI Dialog component. App works fine but i want to solve the warning, do you know how can i solve it ?
here is a link to material ui component:
https://mui.com/material-ui/react-dialog/
Note: before adding the dialog component everything worked fine.
Thanks in advance for everyone answering !
import * as React from 'react';
import Avatar from '#mui/material/Avatar';
import Button from '#mui/material/Button';
import CssBaseline from '#mui/material/CssBaseline';
import TextField from '#mui/material/TextField';
import FormControlLabel from '#mui/material/FormControlLabel';
import Checkbox from '#mui/material/Checkbox';
import Link from '#mui/material/Link';
import Grid from '#mui/material/Grid';
import Box from '#mui/material/Box';
import LockOutlinedIcon from '#mui/icons-material/LockOutlined';
import Typography from '#mui/material/Typography';
import Container from '#mui/material/Container';
import { createTheme, ThemeProvider } from '#mui/material/styles';
import axios from "axios";
import Switch from '#mui/material/Switch';
import Dialog from '#mui/material/Dialog';
import DialogActions from '#mui/material/DialogActions';
import DialogContent from '#mui/material/DialogContent';
import DialogContentText from '#mui/material/DialogContentText';
import DialogTitle from '#mui/material/DialogTitle';
import Slide from '#mui/material/Slide';
import {useNavigate} from "react-router-dom";
import {useState} from "react";
function Copyright(props) {
return (
<Typography variant="body2" color="text.secondary" align="center" {...props}>
{'Copyright © '}
<Link color="inherit" href="https://mui.com/">
Your Website
</Link>{' '}
{new Date().getFullYear()}
{'.'}
</Typography>
);
}
const theme = createTheme();
const Transition = React.forwardRef(function Transition(props, ref) {
return <Slide direction="up" ref={ref} {...props} />;
});
export default function SignIn() {
const history = useNavigate();
const [dialogueMessage,setDialogueMessage] = useState('')
const [checked, setChecked] = useState(true);
const handleChange = (event) => {
setChecked(event.target.checked);
};
const [iopen, setOpen] = useState(false);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
const handleSubmit = (event) => {
event.preventDefault();
const data = new FormData(event.currentTarget);
const username = data.get('email').split("#")[0];
if (checked === false ) {
console.log("post")
axios.post(process.env.REACT_APP_LOCAL_HOST + "/users/login", {
email: data.get('email'),
password: data.get('password')
}).then((resp) => {
console.log(resp.data)
history("/users/" + username,{state:{token:resp.data.token,email:data.get('email'),user_id:resp.data.item.id}})
})
}else{
axios.post(process.env.REACT_APP_LOCAL_HOST + "/admin/login", {
email: data.get('email'),
password: data.get('password')
}).then((resp) => {
if(resp.data.success === false){
handleClickOpen()
setDialogueMessage(resp.data.message)
}else {
history("/admin/" + username, {state: {token: resp.data.token, email: data.get('email')}})
}
})
}
};
return (
<ThemeProvider theme={theme}>
<Container component="main" maxWidth="xs">
<Dialog
open={iopen}
TransitionComponent={Transition}
keepMounted
onClose={handleClose}
aria-describedby="alert-dialog-slide-description"
>
<DialogTitle>{"There is a problem with your login !"}</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-slide-description">
{dialogueMessage}
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Disagree</Button>
<Button onClick={handleClose}>Agree</Button>
</DialogActions>
</Dialog>
<CssBaseline />
<Box
sx={{
marginTop: 8,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
}}
>
<Avatar sx={{ m: 1, bgcolor: 'secondary.main' }}>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
Log in
</Typography>
<Box component="form" onSubmit={handleSubmit} noValidate sx={{ mt: 1 }}>
<TextField
margin="normal"
required
fullWidth
id="email"
label="Email Address"
name="email"
autoComplete="email"
autoFocus
/>
<TextField
margin="normal"
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
autoComplete="current-password"
/>
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Remember me"
/>
<Switch
checked={checked}
onChange={handleChange}
inputProps={{ 'aria-label': 'controlled' }}
/>
Are you an admin ?
<Button
type="submit"
fullWidth
variant="contained"
sx={{ mt: 3, mb: 2 }}
>
Log In
</Button>
<Grid container>
<Grid item xs>
<div/>
</Grid>
<Grid item>
<Link href="/register" variant="body2">
{"Don't have an account? Register"}
</Link>
</Grid>
</Grid>
</Box>
</Box>
{/*<Copyright sx={{ mt: 8, mb: 4 }} />*/}
</Container>
</ThemeProvider>
);
}
When the page loads, the API call has not yet resolved so you get the warning. Eventually (if you see it), the data will populate after the API call is resolved.
I got the same issue once I forget to initiate my open dialog state which make sense cause living the state without initiating return the value undefined
const [dialog, setDialog] = useState()
Warning: Failed prop type: The prop `open` is marked as required in `ForwardRef(Dialog)`, but its value is `undefined`.
after initiating my state the issue dispear
const [dialog, setDialog] = useState(false)

Object is Not a Function in firebase PhoneAuthentication

I am building a form where I have to login into the user by their phone number on CLICKING the send code button I got an error TypeError: Object(...) is not a function where it says that window is not a function can anybody solve my problem.
Error Image
Here is some of my code
import * as React from "react";
import { useState } from "react";
import Avatar from "#mui/material/Avatar";
import Button from "#mui/material/Button";
import ButtonGroup from "#mui/material/ButtonGroup";
import CssBaseline from "#mui/material/CssBaseline";
import TextField from "#mui/material/TextField";
import FormControlLabel from "#mui/material/FormControlLabel";
import Checkbox from "#mui/material/Checkbox";
import Link from "#mui/material/Link";
import Paper from "#mui/material/Paper";
import Box from "#mui/material/Box";
import Grid from "#mui/material/Grid";
import LockOutlinedIcon from "#mui/icons-material/LockOutlined";
import Typography from "#mui/material/Typography";
import { createTheme, ThemeProvider } from "#mui/material/styles";
import background from "../staticfiles/signin-background.jpg";
import "react-phone-input-2/lib/style.css";
import { auth, db, captcha } from "../config/Config";
import { RecaptchaVerifier } from "firebase/auth";
import { Link as RouterLink } from "react-router-dom";
import { useHistory } from "react-router-dom";
import socialMediaAuth from "../service/auth";
function Copyright(props) {
return (
<Typography
variant="body2"
color="text.secondary"
align="center"
{...props}
>
{"Copyright © "}
<Link color="inherit" href="https://mui.com/">
Your Website
</Link>{" "}
{new Date().getFullYear()}
{"."}
</Typography>
);
}
const theme = createTheme();
export default function SignInUserPhone() {
let history = useHistory();
const [PhoneNumber, setPhoenNumber] = useState("");
const [VerificationCode, setVerificationCode] = useState("");
const [error, setError] = useState("");
const handleSubmit = (event) => {
event.preventDefault();
console.log(PhoneNumber);
console.log(error);
};
const handleSubmit2 = (e) => {
e.preventDefault();
console.log(VerificationCode);
};
const handleOnClick = async (provider) => {
const res = await socialMediaAuth(provider);
await db
.collection("SignedUpUsersData")
.doc(res.uid)
.set({
Email: res.email,
Name: res.displayName,
})
.then(() => {
history.push("/");
})
.catch((err) => setError(err.message));
};
const handleUserButton = (event) => {
event.preventDefault();
history.push("/signinuser");
};
const handleSellerButton = (event) => {
event.preventDefault();
history.push("/signinseller");
};
auth.languageCode = "it";
const setUpCaptcha = () => {
window.recaptchaVerifier = auth().RecaptchaVerifier("recaptcha-container", {
size: "invisible",
callback: (response) => {
// reCAPTCHA solved, allow signInWithPhoneNumber.
console.log(response);
console.log("Ok recapthca sloved");
onSignInSubmit();
},
});
};
const onSignInSubmit = (e) => {
e.preventDefault();
setUpCaptcha();
const phoneNumber = PhoneNumber;
const appVerifier = window.recaptchaVerifier;
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;
console.log(confirmationResult);
// ...
})
.catch((error) => {
// Error; SMS not sent
// ...
console.log(error.message);
//( Or, if you haven't stored the widget ID:
});
};
return (
<ThemeProvider theme={theme}>
<Grid container component="main" sx={{ height: "100vh" }}>
<CssBaseline />
<Grid
item
xs={false}
sm={4}
md={7}
sx={{
backgroundImage: `url(${background})`,
backgroundRepeat: "no-repeat",
backgroundColor: (t) =>
t.palette.mode === "light"
? t.palette.grey[50]
: t.palette.grey[900],
backgroundSize: "cover",
backgroundPosition: "center",
}}
/>
<Grid item xs={12} sm={8} md={5} component={Paper} elevation={6} square>
<Box
sx={{
my: 8,
mx: 4,
display: "flex",
flexDirection: "column",
alignItems: "center",
}}
>
<Avatar sx={{ m: 1, bgcolor: "secondary.main" }}>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
Sign in With Phone Number
</Typography>
<Box
sx={{
my: 4,
mx: 4,
display: "flex",
flexDirection: "column",
alignItems: "center",
}}
>
<ButtonGroup size="large" disableElevation variant="contained">
<Button onClick={handleSellerButton}>SELLER</Button>
<Button onClick={handleUserButton}>USER</Button>
</ButtonGroup>
</Box>
<Box
component="form"
noValidate
onSubmit={onSignInSubmit}
sx={{ mt: 1 }}
>
<TextField
margin="normal"
required
fullWidth
id="email"
label="Phone Number"
name="Phone"
autoComplete="phoenumber"
value={PhoneNumber}
onChange={(phone) => setPhoenNumber(phone.target.value)}
/>
<div id="recaptcha-container"></div>
<Button
type="submit"
fullWidth
variant="contained"
sx={{ mt: 3, mb: 2 }}
onSubmit={onSignInSubmit}
id="sign-in-button"
>
Send Code
</Button>
<Grid container>
<Grid item xs></Grid>
<Grid item>
<Link
component={RouterLink}
to="/signup"
href="#"
variant="body2"
>
{"Don't have an account? Sign Up"}
</Link>
</Grid>
</Grid>
</Box>
{error && <div>{error}</div>}
<Box
component="form"
noValidate
onSubmit={handleSubmit2}
sx={{ mt: 1 }}
>
<TextField
margin="normal"
required
fullWidth
id="email"
label="Verification Code"
name="Verification"
autoComplete="Verification"
value={VerificationCode}
onChange={(verification) =>
setVerificationCode(verification.target.value)
}
/>
<Button
type="submit"
fullWidth
variant="contained"
sx={{ mt: 3, mb: 2 }}
>
Submit
</Button>
<Copyright sx={{ mt: 5 }} />
</Box>
</Box>
</Grid>
</Grid>
</ThemeProvider>
);
}
All the files are correctly exported from config js cause sign in with email and password and sign in with social media are working
React uses a virtual DOM so doesn't have the same access to window as writing a website with pure javascript. So accessing the window object will often cause issues.
This does seem to be a duplicate of this answer though. That might help you fix the bug

How can I load user every time the page is refreshed?

How can i make the relevant asp.net controller for this?
I have added the 'load user' functions to App.js also. What I want is to load the user every time the page is refreshed. The login function is working properly but when the page is refreshed the authentication will be null again.
"export const loadUser = () => async (dispatch) => {
if (localStorage.token) {
setAuthToken(localStorage.token);
}
try {
const res = await axios.get('https://localhost:5001/api/auth/user');
dispatch({
type: USER_LOADED,
payload: res.data,
});
} catch (err) {
dispatch({
type: AUTH_ERROR,
});
}
};"
This is the login page
import React, { useState } from 'react';
import Avatar from '#material-ui/core/Avatar';
import Button from '#material-ui/core/Button';
import TextField from '#material-ui/core/TextField';
import FormControlLabel from '#material-ui/core/FormControlLabel';
import Checkbox from '#material-ui/core/Checkbox';
import Link from '#material-ui/core/Link';
import Paper from '#material-ui/core/Paper';
import Box from '#material-ui/core/Box';
import Grid from '#material-ui/core/Grid';
import LockOutlinedIcon from '#material-ui/icons/LockOutlined';
import Typography from '#material-ui/core/Typography';
import { makeStyles } from '#material-ui/core/styles';
import { pink } from '#material-ui/core/colors';
import { connect } from 'react-redux';
import { setAlert } from '../../actions/alert';
import PropTypes from 'prop-types';
import {login} from '../../actions/auth'
import { Redirect } from 'react-router-dom'
function Copyright() {
return (
<Typography variant="body2" color="textSecondary" align="center">
{'Copyright © '}
<Link color="primary" href="./">
NoQueue Website
</Link>{' '}
{new Date().getFullYear()}
{'.'}
</Typography>
);
}
const useStyles = makeStyles((theme) => ({
root: {
height: '100vh',
},
image: {
backgroundImage: 'url(https://invention.si.edu/sites/default/files/styles/story_banner_image/public/blog-guest-fox-susannah-2017-03-09-shutterstock_189632216-banner-edit.jpg?itok=eNxGJoO4)',
backgroundSize: 'cover',
backgroundPosition: 'center',
},
paper: {
margin: theme.spacing(8, 4),
display: 'flex',
flexDirection:'column',
alignItems: 'center',
},
avatar: {
margin: theme.spacing(1),
backgroundColor: pink.A700,
},
form: {
width: '100%',
marginTop: theme.spacing(2),
},
submit: {
margin: theme.spacing(3,0,2),
},
}));
const SignIn = ({setAlert,login,isAuthenticated,user}) => {
const [formData, setFormData] = useState({
email:"",
password:"",
})
const{email,password}=formData;
const onChange=e=>setFormData(
{
...formData, [e.target.name]:e.target.value
}
)
const onSubmit=async e=>{
e.preventDefault();
if (email && password) {
login(email,password)
}
else{
setAlert('Please fill all the fileds','warning');
}
}
const classes = useStyles();
if(isAuthenticated){
//if(user.role === 'User')
//return <Redirect to="/index"/>
//else if(
//user.role ==='Admin'
//)
return <Redirect to="/business"/>
}
return (
<Grid container component="main" className={classes.root}>
<Grid item xs={false} sm={4} md={7} className={classes.image} />
<Grid item xs={12} sm={8} md={5} component={Paper} square>
<div className={classes.paper}>
<Avatar className={classes.avatar}>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
Sign in
</Typography>
<form onSubmit = { e=>onSubmit(e)} className={classes.form} noValidate>
<TextField
onChange={e=>onChange(e)}
variant="outlined"
margin="normal"
required
fullWidth
id="email"
label="Email Address"
name="email"
value={email}
/>
<TextField
onChange={e=>onChange(e)}
variant="outlined"
margin="normal"
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
value={password}
/>
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Remember me"
/>
<Button
type="submit"
fullWidth
variant="contained"
color="Primary"
className={classes.submit}
>
Sign In
</Button>
<Grid container>
<Grid item xs>
<Link href="forgotpassword" variant="body2">
Forgot password?
</Link>
</Grid>
<Grid item>
<Link href="signup" variant="body2">
{"Not a member? Sign Up"}
</Link>
</Grid>
</Grid>
<Box mt={5}>
<Copyright />
</Box>
</form>
</div>
</Grid>
</Grid>
);
}
SignIn.propTypes={
login:PropTypes.func.isRequired,
setAlert:PropTypes.func.isRequired,
isAuthenticated:PropTypes.bool,
user: PropTypes.object.isRequired,
};
const mapStateToProps=state=>({
isAuthenticated:state.auth.isAuthenticated,
user: state.auth.user,
})
export default connect(mapStateToProps,{login,setAlert})(SignIn);
I think in initial state of redux you need to check whether or not localStorage.token is not null/expired and set it back to user. So that whenever you refresh the page user da still can load
I was able to resolve above issue by using jwt_decode
if (localStorage.token) {
setAuthToken(localStorage.token);
var decoded = jwt_decode(localStorage.token);
}
try {
const res = await axios.get(`https://localhost:5001/api/auth/user/${decoded.Id}`);
dispatch({
type: USER_LOADED,
payload: res.data,
});
} catch (err) {
dispatch({
type: AUTH_ERROR,
});
}
};

Using axios to make use of a service not working

I'm trying to use S3 service to upload an image and it's telling me that certain variables aren't defined when I have defined them. I have imported axios and all the other stuff that are required
import React, { useState } from "react";
import ReactDOM from "react-dom";
import axios from "axios";
import Grid from "#material-ui/core/Grid";
import Button from "#material-ui/core/Button";
import Card from "#material-ui/core/Card";
import TextField from "#material-ui/core/TextField";
import CreateIcon from "#material-ui/icons/Create";
import Box from "#material-ui/core/Box";
import CardMedia from "#material-ui/core/CardMedia";
import MuiAlert from "#material-ui/lab/Alert";
import Snackbar from "#material-ui/core/Snackbar";
import { withStyles } from "#material-ui/core/styles";
import { makeStyles } from "#material-ui/core/styles";
import Chip from "#material-ui/core/Chip";
import Avatar from "#material-ui/core/Avatar";
import Slider from "#material-ui/core/Slider";
import Typography from "#material-ui/core/Typography";
import InputAdornment from "#material-ui/core/InputAdornment";
import { connect } from "react-redux";
function mapStateToProps(state) {
return {};
}
const useStyles = makeStyles((theme) => ({
root: {
"& > *": {
margin: theme.spacing(1),
marginLeft: theme.spacing(15),
},
},
input: {
display: "none",
},
}));
const useSliderStyles = makeStyles({
root: {
width: 250,
},
input: {
width: 100,
},
});
const UploadButton = () => {
const classes = useStyles();
return (
<div className={classes.root}>
<input
accept='image/*'
className={classes.input}
id='contained-button-file'
multiple
type='file'
/>
<label htmlFor='contained-button-file'>
<Button variant='contained' color='primary' component='span'>
Upload
</Button>
</label>
</div>
);
};
const StyledCard = withStyles({
root: { height: 600, width: 350 },
})(Card);
const PetitionForm = () => {
const [title, setTitle] = useState("");
const [description, setDescription] = useState("");
const [open, setOpen] = useState(false);
const [petition, validPetition] = useState(false);
const [noTitle, titleError] = useState(false);
const [noDescription, descriptionError] = useState(false);
const [hashtag, setHashtag] = useState("");
const [arrayOfHashtags, addHashtag] = useState([]);
const [money, setMoney] = React.useState(500);
const slider = useSliderStyles();
const handleTitleChange = (event) => setTitle(event.target.value);
const handleDescriptionChange = (event) => setDescription(event.target.value);
const handleClose = (event, reason) => {
if (reason === "clickaway") {
return;
}
};
const Alert = (props) => (
<MuiAlert elevation={6} variant='filled' {...props} />
);
const clearField = (event) => {
setOpen(true);
if (title.length > 0 && description.length > 0) {
validPetition(true);
setTitle("");
setDescription("");
addHashtag([]);
setHashtag("");
axios({
url: `call/s3/backend`,
method: "post",
data: {
images: imageArray.toByteArray(),
},
})
.then((res) => {
imageUrlArr = res.data;
axios({
url: `api/petition_posts`,
method: "post",
data: {
petition_post: {
title: title,
description: description,
hashtags: arrayOfHashtags.join(" "),
amount_donated: 0,
media: imageUrlArr,
goal: money,
card_type: "petition",
org_profile_id: 1,
},
},
})
.then((res) => {
console.log(res.data);
})
.catch((error) => console.log(error));
})
.catch((error) => console.log(error));
}
titleError(true ? title.length === 0 : false);
descriptionError(true ? description.length === 0 : false);
};
const handleDelete = (h) => () => {
addHashtag((arrayOfHashtags) =>
arrayOfHashtags.filter((hashtag) => hashtag !== h)
);
};
const handleHashtagChange = (event) => setHashtag(event.target.value);
const handleSliderChange = (event, newValue) => {
setMoney(newValue);
};
const handleInputChange = (event) => {
setMoney(event.target.value === "" ? "" : Number(event.target.value));
};
const newHashtag = () => {
if (arrayOfHashtags.length < 3) {
addHashtag((arrayOfHashtags) => arrayOfHashtags.concat(hashtag));
} else {
console.log("Too many hashtags");
}
};
const Hashtags = arrayOfHashtags.map((h) => (
<Chip
key={h.length}
size='small'
avatar={<Avatar>#</Avatar>}
label={h}
onDelete={handleDelete(h)}
/>
));
return (
<StyledCard>
<Box mt={1}>
<Grid container justify='center'>
<TextField
id='outlined-multiline-static'
multiline
rows={1}
variant='outlined'
placeholder='Title'
value={title}
onChange={handleTitleChange}
helperText={
open // only displays helper text if button has been clicked and fields haven't been filled
? !noTitle || petition
? ""
: "Can't be an empty field"
: ""
}
/>
</Grid>
</Box>
<Box mt={1}>
<Grid container justify='center'>
<CardMedia title='Petition'>
<UploadButton />
</CardMedia>
</Grid>
</Box>
<div className={slider.root}>
<Typography>Amount to raise</Typography>
<Box>
<Grid container justify='center'>
<Slider
min={500}
max={10000}
value={typeof money === "number" ? money : 0}
onChange={handleSliderChange}
aria-labelledby='input-slider'
/>
<TextField
className={slider.input}
value={money}
onChange={handleInputChange}
InputProps={{
startAdornment: (
<InputAdornment position='start'>$</InputAdornment>
),
}}
helperText={
money < 500 || money > 10000
? "Please enter a value between 500 and 10000"
: ""
}
/>
</Grid>
</Box>
</div>
<Box mt={1} mb={1}>
<Grid container justify='center'>
<TextField
size='small'
inputProps={{
style: { fontSize: 15 },
}}
id='outlined-multiline-static'
multiline
rows={1}
placeholder='Hashtags'
variant='outlined'
value={hashtag}
onChange={handleHashtagChange}
helperText={
arrayOfHashtags.length === 3
? "You reached the maximum amount of hashtags"
: ""
}
/>
<Button color='primary' onClick={newHashtag}>
Create!
</Button>
{arrayOfHashtags.length > 0 ? Hashtags : ""}
</Grid>
</Box>
<Box mt={1} justify='center'>
<Grid container justify='center'>
<TextField
size='small'
inputProps={{
style: { fontSize: 15 },
}}
id='outlined-multiline-static'
multiline
rows={5}
placeholder='Description'
variant='outlined'
value={description}
onChange={handleDescriptionChange}
helperText={
// only displays helper text if button has been clicked and fields haven't been filled
open
? !noDescription || petition
? ""
: "Can't be an empty field"
: ""
}
/>
</Grid>
</Box>
<Box mt={1}>
<Grid container justify='center'>
<Button onClick={clearField}>
<CreateIcon />
Create Petition!
</Button>
{open && petition && (
<Snackbar open={open} autoHideDuration={2000} onClose={handleClose}>
<Alert severity='success'>
You have successfully create a petition!
</Alert>
</Snackbar>
)}
{open && !petition && (
<Snackbar open={open} autoHideDuration={2000} onClose={handleClose}>
<Alert severity='error'>You're missing one or more fields</Alert>
</Snackbar>
)}
</Grid>
</Box>
</StyledCard>
);
};
export default connect(mapStateToProps)(PetitionForm);
This is the error I'm getting, someone mentioned something about the scope and I think that shouldn't matter when I'm trying to assign a value to a variable as far I as know
Line 109:19: 'imageArray' is not defined no-undef
Line 113:11: 'imageUrlArr' is not defined no-undef
Line 123:24: 'imageUrlArr' is not defined no-undef
Search for the keywords to learn more about each error.

Redirection with useEffect() Not Working?

If the login is successful and a token is stored in localStorage, I should be redirected to a private route i.e /panel. If not, I should show the error message from ShowError().
Currently, my error message is being displayed if the login is not successful so it's all good. However, if there is a token present, there is still no redirection.
function LoginPage (){
const [state, setState] = useState({
email: '',
password: '',
});
const [submitted, setSubmitted] = useState(false);
const [shouldRedirect, setShouldRedirect] = useState(false);
function ShowError(){
if (!localStorage.getItem('token'))
{
console.log('Login Not Successful');
return (
<ThemeProvider theme={colortheme}>
<Typography color='primary'>
Login Unsuccessful
</Typography>
</ThemeProvider>)
}
}
// function FormSubmitted(){
// setSubmitted(true);
// console.log('Form submitted');
// }
// function RedirectionToPanel(){
// console.log('check');
// if(submitted && localStorage.getItem('token')){
// console.log('Finall');
// return <Redirect to='/panel'/>
// }
// }
useEffect(() => {
if(localStorage.getItem('token')){
setShouldRedirect(true);
}
},[] );
function submitForm(LoginMutation: any) {
setSubmitted(true);
const { email, password } = state;
if(email && password){
LoginMutation({
variables: {
email: email,
password: password,
},
}).then(({ data }: any) => {
localStorage.setItem('token', data.loginEmail.accessToken);
})
.catch(console.log)
}
}
return (
<Mutation mutation={LoginMutation}>
{(LoginMutation: any) => (
<Container component="main" maxWidth="xs">
<CssBaseline />
<div style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center'
}}>
<Avatar>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
Sign in
</Typography>
<Formik
initialValues={{ email: '', password: '' }}
onSubmit={(values, actions) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
actions.setSubmitting(false);
}, 1000);
}}
validationSchema={schema}
>
{props => {
const {
values: { email, password },
errors,
touched,
handleChange,
isValid,
setFieldTouched
} = props;
const change = (name: string, e: any) => {
e.persist();
handleChange(e);
setFieldTouched(name, true, false);
setState( prevState => ({ ...prevState, [name]: e.target.value }));
};
return (
<form style={{ width: '100%' }}
onSubmit={e => {e.preventDefault();
submitForm(LoginMutation);}}>
<TextField
variant="outlined"
margin="normal"
id="email"
fullWidth
name="email"
helperText={touched.email ? errors.email : ""}
error={touched.email && Boolean(errors.email)}
label="Email"
value={email}
onChange={change.bind(null, "email")}
/>
<TextField
variant="outlined"
margin="normal"
fullWidth
id="password"
name="password"
helperText={touched.password ? errors.password : ""}
error={touched.password && Boolean(errors.password)}
label="Password"
type="password"
value={password}
onChange={change.bind(null, "password")}
/>
{submitted && ShowError()}
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Remember me"
/>
<br />
<Button className='button-center'
type="submit"
disabled={!isValid || !email || !password}
// onClick={handleOpen}
style={{
background: '#6c74cc',
borderRadius: 3,
border: 0,
color: 'white',
height: 48,
padding: '0 30px'
}}
>
Submit</Button>
<br></br>
<Grid container>
<Grid item xs>
<Link href="#" variant="body2">
Forgot password?
</Link>
</Grid>
<Grid item>
<Link href="#" variant="body2">
{"Don't have an account? Sign Up"}
</Link>
</Grid>
</Grid>
</form>
)
}}
</Formik>
</div>
<Box mt={8}>
<Copyright />
</Box>
{/* {submitted && <Redirect to='/panel'/>} */}
</Container>
)
}
</Mutation>
);
}
export default LoginPage;
My App.tsx:
const token = localStorage.getItem('token');
const PrivateRoute = ({component, isAuthenticated, ...rest}: any) => {
const routeComponent = (props: any) => (
isAuthenticated
? React.createElement(component, props)
: <Redirect to={{pathname: '/404'}}/>
);
return <Route {...rest} render={routeComponent}/>;
};
export default function App() {
return (
<div>
<BrowserRouter>
<Switch>
<Route exact path='/' component= {HomePage}></Route>
<Route path='/login' component= {LoginPage}></Route>
<Route path='/404' component= {Error404Page}></Route>
<PrivateRoute
path='/panel'
isAuthenticated={token}
component={PanelHomePage}
/>
<Redirect from='*' to='/404' />
</Switch>
</BrowserRouter>
</div>
);
}
Why do you use useState to redirect? Just redirect directly. And if you are using react-router it is good to use useHistory.
import { useHistory } from 'react-router-dom';
const history = useHistory();
useEffect(() => {
if(localStorage.getItem('token')){
history.push({
pathname: '/',
});
}
},[]);
If you still want to use useState you can create a new useEffect NS add that state into your dependency array.
const history = useHistory();
useEffect(() => {
if(localStorage.getItem('token')){
setShouldRedirect(true);
}
},[]);
useEffect(() => {
if(shouldRedirect){
history.push({
pathname: '/',
});
}
},[shouldRedirect]);

Categories