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
Related
I am having some trouble with the useNavigate function from React-Router v6. My main goal is to prevent the user from logging themselves out and returning to the home page, when pressing the browser back button.
The issue I am having is when the browser back button is pressed, my application treats that as a log out and returns to the login page. I would like to alter that so when the browser back button is pressed, the user is returned/remains on the homepage. A logout should only occur when the user manually logs themselves out, by selecting the logout button.
I believe I have set up my homepage useNavigate functions properly, yet as I am still learning the process, I may have missed a few things. Below is the code for the main pages in question: login page, home page and privateroutes.js (this function is what protects the private routes by checking is user is logged in).
Homepage.js
import { AppBar, Toolbar, IconButton, Typography, Box } from '#mui/material';
import { Menu } from '#mui/icons-material';
import { ThemeProvider } from '#mui/material/styles';
import { useLocation } from 'react-router-dom';
import { theme } from '../../App';
import { GeneratorComp } from '../../components/GeneratorComp/generatorcomp';
import './home.css';
import { SideMenu } from '../../components/SideMenu/sidemenu';
export function Home() {
const location = useLocation();
const [open, setOpen] = useState(false);
const handleDrawerOpen = () => {
setOpen(true);
};
const handleDrawerClose = () => {
setOpen(false);
};
return (
<ThemeProvider theme={theme}>
<Box component='nav' sx={{ flexGrow: 1 }}>
<AppBar position='static'>
<Toolbar>
<IconButton onClick={handleDrawerOpen} size='large'>
<Menu fontSize='large' sx={{color: 'white'}}/>
</IconButton>
<SideMenu open={open} onClose={handleDrawerClose}/>
<Typography variant='h4' sx={{ml: 2, mr: 2, flexGrow: 1, textAlign: {xs: 'center', sm: 'start'}}}>Welcome, {location.state.user.username}</Typography>
</Toolbar>
</AppBar>
</Box>
<Box component='main'>
<Typography className="subhead-title" variant="h5" sx={{mt: 3}}>
Generate your passwords below!
</Typography>
<GeneratorComp theme={theme}/>
</Box>
</ThemeProvider>
)
};
Login.js
import Axios from 'axios';
import { Box, AppBar, Toolbar, TextField, Typography, Button } from '#mui/material';
import { ThemeProvider } from '#mui/material/styles';
import { useLocation, useNavigate } from 'react-router-dom';
import { theme } from '../../App'
export function Login() {
const [loginUsername, setLoginUsername] = useState('');
const [loginPassword, setLoginPassword] = useState('');
const [loginStatus, setLoginStatus] = useState(false);
const [userInfo, setUserInfo] = useState({});
const navigate = useNavigate();
const location = useLocation();
const login = async () => {
await Axios.post('http://localhost:3001/login', {
username: loginUsername,
password: loginPassword,
}).then((res) => {
if (!res.data.message) {
setLoginStatus(true);
setUserInfo(res.data.result[0]);
} else {
document.getElementById('submitMessage').innerHTML = res.data.message;
document.getElementById('submitMessage').style.color = 'red';
}
});
};
useEffect(() => {
if (loginStatus) {
navigate('/home', {state: {status: loginStatus, user: userInfo}, replace: true} );
};
console.log(location.state);
}, [navigate,loginStatus, userInfo, location]);
return (
<ThemeProvider theme={theme}>
<Box sx={{display: 'flex', flexDirection:'column', justifyContent: 'center', alignItems: 'center'}}>
<Box component='nav' sx={{ flexGrow: 1, margin: 0, width: '100%' }}>
<AppBar position='static'>
<Toolbar>
<Typography variant='h4' sx={{display: {xs: 'none', sm:'block'}, flexGrow:1, textAlign:'start', letterSpacing: {xs: 'none', sm: '0.4em',md:'0.6em'}}}>Passwordinator</Typography>
<Button color='inherit' onClick={() => {navigate('/generator', {state: {status: loginStatus, user: userInfo}})}}>Generator</Button>
<Button color='inherit' onClick={() => {navigate('/signup', {state: {status: loginStatus, user: userInfo}})}}>Signup</Button>
</Toolbar>
</AppBar>
</Box>
<Box component='form' sx={{display: 'flex', flexDirection: 'column', width: '90%',maxWidth: '500px', m: 4}}>
<Typography variant='h2' color='#ffffff' sx={{mb: '70px'}}>Welcome Back!</Typography>
<TextField id="input" label="Username" variant="outlined" onChange={(e) => {setLoginUsername(e.target.value)}} sx={{mt: 2, mb: 2}}/>
<TextField id="input" label="Password" variant="outlined" onChange={(e) => {setLoginPassword(e.target.value)}} sx={{mt: 2, mb: 10}}/>
</Box>
<Button color='primary' variant='contained' size='large' onClick={login} sx={{mb:8}}>Login</Button>
<Typography id='submitMessage' variant='h6' ></Typography>
</Box>
</ThemeProvider>
)
};
privateroutes.js
import {Outlet, Navigate, useLocation } from 'react-router-dom';
export const PrivateRoutes = () => {
const location = useLocation();
console.log(location.state);
return (
location.state && location.state.status ? <Outlet replace/> : <Navigate to='/login' />
);
}
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)
I'm creating a e-commerce website. But i'm unable to update the total price using the useState hook of react.
When is use forEach to update total price it give me this error: Uncaught (in promise) Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
codes:
import { Container, Grid, Typography } from "#mui/material";
import React, { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import useAuth from "../../../hooks/useAuth";
import Cart from "../Cart/Cart";
import CartProduct from "../CartProduct/CartProduct";
const CartContainer = () => {
const { user } = useAuth();
// useNavigate hook
const navigate = useNavigate();
/* states */
const [products, setProducts] = useState([]);
const [quantity, setQuantity] = useState(0);
const [isDeleted, setIsDeleted] = useState(false);
const [total, setTotal] = useState(0);
const handleAddQuantity = () => {
setQuantity(quantity + 1);
};
const handleRemoveQuantity = () => {
if (quantity === 0) {
return;
} else {
setQuantity(quantity - 1);
}
};
const handleDelete = (id) => {
fetch(`https://limitless-crag-38673.herokuapp.com/cart?id=${id}`, {
method: "DELETE",
})
.then((res) => res.json())
.then((data) => {
data.deletedCount > 0 && setIsDeleted(true);
alert("successfully deleted");
});
};
useEffect(() => {
setIsDeleted(false);
fetch(
`https://limitless-crag-38673.herokuapp.com/cart/product?email=${user.email}`
)
.then((res) => res.json())
.then((data) => setProducts(data));
}, [isDeleted]);
return (
<>
{/* main cart */}
<Container sx={{ my: 3 }} maxWidth="xl">
<Grid container spacing={{ xs: 1, md: 2 }}>
{/* products */}
<Grid item md={8} xs={12}>
{/* cart title */}
<Grid
container
sx={{
borderBottom: "1px solid gray",
display: { xs: "none", sm: "flex" },
}}
>
<Grid item md={6}>
<Typography variant="h5">Product</Typography>
</Grid>
<Grid item md={4}>
<Typography variant="h5" sx={{ textAlign: "center" }}>
Price
</Typography>
</Grid>
{/* <Grid item md={2}>
<Typography variant="h5" sx={{ textAlign: "center" }}>
Quantity
</Typography>
</Grid>
<Grid item md={2}>
<Typography variant="h5" sx={{ textAlign: "center" }}>
Subtotal
</Typography>
</Grid> */}
<Grid item md={2}>
<Typography variant="h5" sx={{ textAlign: "center" }}>
Cancel
</Typography>
</Grid>
</Grid>
{/*============
product
============= */}
{products.map((product) => (
<CartProduct
key={product._id}
product={product}
handleDelete={handleDelete}
total={total}
setTotal={setTotal}
/>
))}
</Grid>
{/*===========
cart
================ */}
<Cart />
</Grid>
</Container>
</>
);
};
export default CartContainer;
`And when I try this it gives me this error: Uncaught (in promise) Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
codes:
import CancelOutlinedIcon from "#mui/icons-material/CancelOutlined";
import { Grid, IconButton, Typography } from "#mui/material";
import { Box } from "#mui/system";
import React from "react";
const CartProduct = ({ product, handleDelete, setTotal, total }) => {
const { name, price, src } = product;
setTotal(total + price);
return (
<Grid
container
sx={{
borderBottom: "1px solid gray",
display: "flex",
flexDirection: { xs: "column", md: "row" },
alignItems: "center",
}}
spacing={{ md: 2, xs: 1 }}
>
{/* product */}
<Grid
sx={{
display: "flex",
alignItems: "center",
flexDirection: { md: "row", xs: "column" },
}}
item
md={6}
xs={12}
>
<Box>
<img src={src} alt="" />
</Box>
<Typography sx={{ ml: 1 }} variant="h6">
{name}
</Typography>
</Grid>
{/* Price */}
<Grid
item
md={4}
sx={{
alignItems: "center",
justifyContent: "center",
display: "flex",
}}
>
<Typography variant="h5">$ {price}</Typography>
</Grid>
{/*
// quantity
<Grid
sx={{
display: "flex",
alignItems: "center",
justifyContent: "flex-start",
}}
item
md={2}
xs={12}
>
<IconButton onClick={handleRemoveQuantity}>
<RemoveCircleOutlineOutlinedIcon />
</IconButton>
<TextField value={quantity} />
<IconButton onClick={handleAddQuantity}>
<AddCircleOutlineOutlinedIcon />
</IconButton>
</Grid>
// Subtotal
<Grid
item
md={2}
xs={12}
sx={{
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<Typography variant="h5">$ {product.price}</Typography>
</Grid> */}
{/* Cancel */}
<Grid
item
md={2}
sx={{
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<IconButton onClick={() => handleDelete(product._id)}>
<CancelOutlinedIcon fontSize="large" />
</IconButton>
</Grid>
</Grid>
);
};
export default CartProduct;
Why not calculate Total in parent component?
because setState automatically triggers re-render and in your case every rerender you trigger another setState.
if you want to store data somewhere without re-render use useRef.
But in your case i would suggest to set Total price in CartContainer
You don't need total and subTotal, you can directly calculate it from product.
The below code need to be in CartProduct as you want to apply delete on individual items.
const [isDeleted, setIsDeleted] = useState(false);
useEffect(() => {
setIsDeleted(false);
fetch(
`https://limitless-crag-38673.herokuapp.com/cart/product?email=${user.email}`
)
.then((res) => res.json())
.then((data) => setProducts(data));
}, [isDeleted]);
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,
});
}
};
I am following this example for a basic login screen. Very new to React but I found it to be pretty simple so far.
Unfortunately, as you can see in the screenshot below, the TextAreas look really bad! It seems like the inner padding is messed up.
I'm not sure what I'm doing wrong.
The fields should look like this:
Here is the code:
import React from 'react';
import { FunctionComponent, useState } from 'react';
import Paper from '#material-ui/core/Paper';
import TextField from '#material-ui/core/TextField';
import FormControlLabel from '#material-ui/core/FormControlLabel';
import Checkbox from '#material-ui/core/Checkbox';
import Button from '#material-ui/core/Button';
import Avatar from '#material-ui/core/Avatar';
import Typography from '#material-ui/core/Typography';
import Grid from '#material-ui/core/Grid';
import IconButton from '#material-ui/core/IconButton';
import InputAdornment from '#material-ui/core/InputAdornment';
import Visibility from '#material-ui/icons/Visibility';
import VisibilityOff from '#material-ui/icons/VisibilityOff';
import { makeStyles } from '#material-ui/core/styles';
export interface ComponentProps {
email: string;
password: string;
name: string;
showPassword: boolean;
}
const useStyles = makeStyles((theme) => ({
root: {
height: '100vh',
},
paper: {
margin: theme.spacing(8, 4),
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
},
sideImage: {
backgroundImage: '',
backgroundRepeat: 'no-repeat',
backgroundColor: theme.palette.grey[900],
backgroundSize: 'cover',
backgroundPosition: 'center',
},
form: {
marginTop: theme.spacing(1),
width: '100%',
},
logo: {
margin: theme.spacing(1),
},
submit: {
margin: theme.spacing(3, 0, 2),
},
}));
export const ReactLoginComponent: FunctionComponent<ComponentProps> = (props) => {
const classes = useStyles();
const [values, setValues] = useState({
email: '',
password: '',
name: 'Davey Jones', // TODO: un hardcode this!
showPassword: false,
});
const handleChange = (prop) => (event: React.ChangeEvent<HTMLInputElement>) => {
setValues({ ...values, [prop]: event.target.value });
};
const handleClickShowPassword = () => {
setValues({ ...values, showPassword: !values.showPassword });
};
const handleMouseDownPassword = (event: React.MouseEvent<HTMLButtonElement>) => {
event.preventDefault();
};
const login = (event: React.MouseEvent<HTMLButtonElement>) => {
event.preventDefault();
alert(`Welcome ${values.name}`);
};
return (
<Grid container component="main" className={classes.root}>
<Grid item xs={12} sm={8} md={7} lg={4} component={Paper} elevation={0}>
<div className={classes.paper}>
<Avatar
src="../../../assets/img/logo/logo-half.png"
alt="Branding"
className={classes.logo}
/>
<Typography component="h1" variant="h6">
Welcome Back {values.name}
</Typography>
<form noValidate className={classes.form}>
{/* Email */}
<TextField
required
fullWidth
autoFocus
id="email"
variant="outlined"
label="Email"
margin="normal"
type="text"
value={values.email}
/>
{/* Password */}
<TextField
required
fullWidth
id="password"
variant="outlined"
label="Password"
margin="normal"
type={values.showPassword ? 'text' : 'password'}
value={values.password}
onChange={handleChange('password')}
autoComplete="current-password"
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
aria-label="Toggle password visibility"
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
>
{values.showPassword ? <Visibility/> : <VisibilityOff/>}
</IconButton>
</InputAdornment>
),
}}
/>
<FormControlLabel
control={<Checkbox value="remember" color="primary"/>}
label="Remember me"
/>
<Button
fullWidth
type="submit"
variant="contained"
size="large"
className={classes.submit}
onClick={login}
>
Sign in
</Button>
</form>
</div>
</Grid>
<Grid item xs={false} sm={4} md={5} lg={8} className={classes.sideImage}>
</Grid>
</Grid>
);
};
Versions:
"react": "^16.12.0"
"#material-ui/core": "^4.10.2"
"#material-ui/icons": "^4.9.1"
"#material-ui/styles": "^4.10.0"
Edit:
I should've mentioned that I'm using React inside an Angular application that is using Angular Material and has global overrides for certain components. This is probably where the issue is coming from. How can I negate those global changes from this React component specifically? Or could I override them in this component?