i have a simple React signup application with firebase authentication. I'm using email and password to register users. Everything is working fine but the user is registered as (anonymous). I have enabled email/password authentication in firebase and I'm using createUserWithEmailAndPassword() function.
import React from "react";
import Card from "#mui/material/Card";
import TextField from "#mui/material/TextField";
import Typography from "#mui/material/Typography";
import Grid from "#mui/material/Grid";
import Box from "#mui/material/Box";
import CardContent from "#mui/material/CardContent";
import Button from "#mui/material/Button";
import Alert from "#mui/material/Alert";
import { auth } from "./../firebase";
import { Link } from "react-router-dom";
import GoogleButton from "react-google-button";
import { GoogleAuthProvider, signInWithRedirect } from "firebase/auth";
export const Signup: React.FC = () => {
const emailRef = React.useRef<any>();
const passwordRef = React.useRef<any>();
const passwordConfirmRef = React.useRef<any>();
const [error, setError] = React.useState("");
const [loading, setLoading] = React.useState<boolean>(false);
const googleSignIn = () => {
const provider = new GoogleAuthProvider();
// signInWithPopup(auth, provider);
signInWithRedirect(auth, provider);
};
async function handleSubmit(e: any) {
e.preventDefault();
if (passwordRef.current.value !== passwordConfirmRef.current.value) {
return setError("Passwords do not match");
}
try {
setError("");
setLoading(true);
await auth.createUserWithEmailAndPassword(
emailRef.current!.value,
passwordRef.current!.value
);
} catch {
setError("Failed to create an account");
}
setLoading(false);
}
const handleGoogleSignIn = async () => {
try {
await googleSignIn();
} catch (error) {
console.log(error);
}
};
return (
<>
<Card sx={{ width: "400px" }}>
<CardContent>
<Typography textAlign="center" variant="h4" m={2}>
Sign Up
</Typography>
{error && (
<Alert severity="error" sx={{ marginBottom: 2 }}>
Passwords do not match
</Alert>
)}
<form onSubmit={handleSubmit}>
<Grid
container
direction="column"
justifyContent="center"
alignItems="stretch"
gap={2}
>
<Grid xs={12} sm={6} item>
<TextField
label="Email"
type="email"
autoComplete="email"
placeholder="Enter your email"
variant="outlined"
fullWidth
required
ref={emailRef}
/>
</Grid>
<Grid xs={12} sm={6} item>
<TextField
label="New Password"
type="password"
autoComplete="new-password"
placeholder="New Password"
variant="outlined"
fullWidth
required
ref={passwordRef}
/>
</Grid>
<Grid xs={12} sm={6} item>
<TextField
label="Confirm Password"
type="password"
autoComplete="new-password"
placeholder="Confirm New Password"
variant="outlined"
fullWidth
required
ref={passwordConfirmRef}
/>
</Grid>
</Grid>
<Button
type="submit"
variant="contained"
sx={{ marginTop: 2 }}
fullWidth
disabled={loading}
>
Sign Up
</Button>
</form>
</CardContent>
</Card>
<Box component="div" marginTop={2} textAlign="center">
<GoogleButton
style={{ width: "100%", marginBottom: 15 }}
onClick={handleGoogleSignIn}
/>
<Typography
variant="body1"
component="a"
href="#"
sx={{ textDecoration: "none" }}
>
<Link to="/login" style={{ textDecoration: "none" }}>
Already have an account? Log in
</Link>
</Typography>
</Box>
</>
);
};
According to the docs you should be passing the auth as the first prop in createUserWithEmailAndPassword(auth, email, password): https://firebase.google.com/docs/auth/web/password-auth#create_a_password-based_account:~:text=createUserWithEmailAndPassword(auth%2C%20email%2C%20password)
Also, make sure your email and password contain values and are not undefined.
try {
setError("");
setLoading(true);
const auth = getAuth();
await auth.createUserWithEmailAndPassword(
auth,
emailRef.current!.value,
passwordRef.current!.value
);
} catch {
setError("Failed to create an account");
}
Related
I'm new with react form, I'm using Material UI and Controller Component, and I'm sending a React Hook form request but not getting any response, form's (HTML form tag) onSubmit event is occurring but handleSubmit is not working I have one more form like that it is working perfectly fine but I don't know why it's not working, can anybody please help me with that
import { Button, useTheme, Grid, TextField, Typography } from '#mui/material';
import WSSelectBox from 'components/common/WSSelect';
import React, { FC } from 'react';
import { Controller, FormProvider, useForm } from 'react-hook-form';
import { isMobile } from 'utils/mediaqueries';
import CheckBoxButton from '../CheckBoxButton';
import { formTypes } from './utils';
import { yupResolver } from '#hookform/resolvers/yup';
import * as yup from 'yup';
import { FormPropTypes } from './type';
const schema = yup
.object()
.shape({
name: yup.string().required(),
residentialCountry: yup.number().required(),
initiator: yup.string().required(),
program: yup.string().required(),
list: yup.string().required(),
})
.required();
const Entities: FC<FormPropTypes> = ({
handleClick,
selectedType,
handleSearch,
}) => {
const theme = useTheme();
const methods = useForm({
resolver: yupResolver(schema),
});
const { handleSubmit, control } = methods;
const onSubmit = (data) => {
// Backend is not done yet
console.log('DataData', data);
};
return (
<FormProvider {...methods}>
<form
onSubmit={(e) => {
e.preventDefault();
console.log('skdjskd', 'Line no 44');
handleSubmit(onSubmit);
}}
>
<Grid container spacing={'16px'}>
{formTypes.map((type) => (
<Grid item xs={6} sm={'auto'} md={'auto'} key={type}>
<CheckBoxButton
key={type}
name={'type'}
value={type}
handleClick={handleClick}
active={type == selectedType ? true : false}
/>
</Grid>
))}
</Grid>
<Grid container pt={4} columnSpacing="20px" rowSpacing={'16px'}>
<Grid item xs={12} sm={12} md={6}>
<Controller
name="name"
render={({
// eslint-disable-next-line #typescript-eslint/no-unused-vars
field: { value, ...otherFieldProps },
fieldState,
}) => (
<TextField
fullWidth
id="sanctions-form-name"
label="Name"
variant="outlined"
helperText={
<p
style={{
position: 'relative',
left: -13,
fontSize: 12,
}}
>
Try to enter the full name or part of it. It is possible
to use original language or the Latin alphabet.
</p>
}
required
error={!!fieldState.error}
{...otherFieldProps}
/>
)}
/>
</Grid>
<Grid item xs={12} sm={6} md={3}>
<WSSelectBox
id="sanctions-form-residential-country"
label="Residential country"
name={'residentialCountry'}
data={['Ten', 'Twenty']}
handleSelect={() => {}}
type={'text'}
control={control}
/>
</Grid>
<Grid item xs={12} sm={6} md={3}>
<WSSelectBox
data={['Ten', 'Twenty']}
handleSelect={() => {}}
id="sanctions-form-initiator"
name={'initiator'}
label="Initiator"
type="text"
control={control}
/>
</Grid>
<Grid item xs={12} sm={6} md={6}>
<WSSelectBox
id="sanctions-form-program"
label="Program"
data={['Ten', 'Twenty']}
handleSelect={() => {}}
type="text"
name={'program'}
control={control}
/>
</Grid>
<Grid item xs={12} sm={6} md={6}>
<WSSelectBox
id="sanctions-form-list"
label="List"
data={['Ten', 'Twenty']}
handleSelect={() => {}}
type={'text'}
name={'list'}
control={control}
/>
</Grid>
</Grid>
<Grid
container
pt={{ xs: '20px', md: '30px' }}
rowSpacing="10px"
alignItems="center"
sx={{
[isMobile(theme)]: {
textAlign: 'center',
},
}}
justifyContent="left"
>
<Grid item xs={6} sm={'auto'}>
<Button
variant="contained"
color="primary"
sx={{
minWidth: '200px',
['#media (max-width:460px)']: {
minWidth: '120px',
},
}}
type="submit"
>
Search
</Button>
</Grid>
<Grid item xs={6} sm={'auto'}>
<Button
sx={{
minWidth: '200px',
color: '#3883FA',
['#media (max-width:460px)']: {
minWidth: '120px',
},
}}
type="submit"
>
Reset
</Button>
</Grid>
</Grid>
</form>
<Typography
variant="body2"
sx={{ fontSize: 17, color: '#121E3D', marginTop: '20px' }}
>
Use filters to start your search.
</Typography>
</FormProvider>
);
};
export default Entities;
SELECT BOX
import { TextField, MenuItem, styled, Select } from '#mui/material';
import { Controller, useForm } from 'react-hook-form';
export type SelectBoxProps = {
label: string;
id: string;
data: Array<string>;
handleSelect: VoidFunction;
type: string;
Control: () => {};
};
const SelectBox = styled(TextField)`
& .MuiOutlinedInput-root:focus {
&.Mui-focused fieldset {
border-bottom: none !important;
}
}
`;
const WSSelectBox = ({
label,
id,
data,
handleSelect,
name,
type,
control,
}) => {
return (
<>
<Controller
name={name}
render={({ field }) => (
<SelectBox
defaultValue=""
fullWidth
autoComplete="off"
id={id}
type={type}
label={label}
variant="outlined"
required
select
{...field}
>
{data.map((opt) => (
<MenuItem key={opt} value={opt}>
{opt}
</MenuItem>
))}
</SelectBox>
)}
control={control}
/>
</>
);
};
export default WSSelectBox;
I'm facing this error when I want to request the backend i checked my backend code on postman it's fine but when i make the request from the front-end it gives that error to me i'm using redux and reac-reudx for my api request from the front-end
there is signup page
export default function Signup() {
const handleSubmit = (event) => {
event.preventDefault();
dispatch(signup(input))
};
const dispatch = useDispatch();
const navigate = useNavigate();
const [input, setinput] = useState('')
// it should be same as the name of the of input fields otherwise it will never be operational
const {Name,email,password}=input
const handlechange=(e)=>setinput({...input,[e.target.name]:e.target.value})
return (
<ThemeProvider theme={theme}>
<Container component="main" maxWidth="xs">
<CssBaseline />
<Box
sx={{
marginTop:20,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
}}
>
<Avatar sx={{ m: 1, bgcolor: 'secondary.main' }}>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
Signup
</Typography>
<Box component="form" noValidate onSubmit={handleSubmit} sx={{ mt: 3 }}>
<Grid container spacing={2}>
<Grid item xs={12}>
<TextField
autoComplete="given-name"
name="Name"
required
fullWidth
id="Name"
label="Name"
autoFocus
onChange={handlechange}
value={Name}
/>
</Grid>
<Grid item xs={12}>
<TextField
required
fullWidth
id="email"
label="Email Address"
name="email"
autoComplete="email"
onChange={handlechange}
value={email}
/>
</Grid>
<Grid item xs={12}>
<TextField
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
autoComplete="new-password"
onChange={handlechange}
value={password}
/>
</Grid>
<Grid item xs={12}>
<FormControlLabel
control={<Checkbox value="allowExtraEmails" color="primary" />}
label="I want to receive inspiration, marketing promotions and updates via email."
/>
</Grid>
</Grid>
<Button
type="submit"
fullWidth
variant="contained"
sx={{ mt: 3, mb: 2 }}
>
Sign Up
</Button>
<Grid container justifyContent="flex-end">
<Grid item style={{paddingRight:'90px'}}>
<Link to="/signup" variant="body2" style={{color:'blue'}}>
If your already have an account
</Link>
</Grid>
</Grid>
</Box>
</Box>
</Container>
</ThemeProvider>
my reducers page
const reducer = (signs = null, action) => {
switch (action.type) {
case SIGN:
return [...signs, action.payload];
default:
return signs;
}
}
here is my action page
export const signup = (formdata) => async (dispatch) => {
try {
const {data} = await api.signUp(formdata);
dispatch({ type: SIGN, payload: data });
console.log(data)
} catch (error) {
console.log(error);
}
};
export const signin = (formdata) => async (dispatch) => {
try {
const {data} = await api.signIn(formdata);
dispatch({ type: SIGN, payload: data });
} catch (error) {
console.log(error);
}
};
I would like when clicking on my accordion, the data in this line will go into the form of my dialog box. But I am not receiving any data in the form.
Why is the form not receiving the data?
import React, { useEffect, useState } from 'react';
import clsx from 'clsx';
import PropTypes from 'prop-types';
import moment from 'moment';
import PerfectScrollbar from 'react-perfect-scrollbar';
import {
Avatar,
Box,
Card,
Accordion,
AccordionSummary,
AccordionDetails,
Grid,
SvgIcon,
InputAdornment,
CardContent,
TextField,
ListItemText,
ListItem,
List,
Checkbox,
Table,
TableBody,
TableCell,
TableHead,
TablePagination,
IconButton,
Typography,
makeStyles,
Button
} from '#material-ui/core';
import ExpandMoreIcon from '#material-ui/icons/ExpandMore';
import getInitials from 'src/utils/getInitials';
import EditProjAdminE from './editProjAdminE';
import AjoutEven from './ajoutEven';
import dataEven from './data';
import SpeedDialTooltipOpen from './speedDialE';
import EditIcon from '#material-ui/icons/Edit';
import AddIcon from '#material-ui/icons/Add';
import { Search as SearchIcon } from 'react-feather';
import { Slide } from 'react-slideshow-image';
import axios from "axios";
import DeleteIcon from '#material-ui/icons/Delete';
const useStyles = makeStyles((theme) => ({
root: {},
absolute: {
position: 'absolute',
bottom: theme.spacing(2),
right: theme.spacing(3),
},
avatar: {
marginRight: theme.spacing(2)
}
}));
const ProjetAdminE = ({ className, dataEleve, ...rest }) => {
const classes = useStyles();
// const [data, setData] = useState(dataEven);
const [filteredEven, setFilteredEven] = useState([]);
const [dataSearch, setDataSearch] = useState([]);
const [loading, setLoading] = useState(false);
const [limit, setLimit] = useState(10);
const [page, setPage] = useState(0);
const [selectedeleveIds, setSelectedeleveIds] = useState([]);
// const dateR = new Date()
// const dateReel = dateR.setDate(dateR.getDate()+1);
const handleLimitChange = (event) => {
setLimit(event.target.value);
};
const handlePageChange = (event, newPage) => {
setPage(newPage);
};
const [search, setSearch] = useState('');
useEffect(() => {
setLoading(true);
axios
.get("http://localhost:8080/employees")
.then((res) => {
setDataSearch(res.data);
setLoading(false);
})
.catch((err) => {
console.log(err);
});
}, []);
const suppression = (id) => {
fetch('http://localhost:8080/evenement/' + id, {
method: 'DELETE',
})
.then(res => res.text())
.then(res => {
// setDataSearch(res.data);
console.log(res)
})
alert(JSON.stringify("événement Numéro " + id + " supprimé"))
}
// const modification =(id) =>{
// fetch('http://localhost:8080/update/' + id, {
// method: 'PUT',
// })
// .then(res => res.text())
// .then(res => console.log(res))
// alert(JSON.stringify("événement Numéro " +id+ " modifié"))
// }
// alert(JSON.stringify(index))
useEffect(() => {
setFilteredEven(
dataSearch.filter((Evenen) =>
Evenen.descrip_evene.toLowerCase().includes(search.toLowerCase())
)
);
}, [search, dataSearch]);
return (
<Card
className={clsx(classes.root, className)}
{...rest}
>
<>
<Box
display="flex"
justifyContent="left"
style={{ height: 30 }}
>
<Typography variant="h3" style={{ margin: 10, color: '#1565C0' }}>
LISTE DES EVENEMENTS
</Typography>
</Box>
<Box mt={3}>
<Card>
<CardContent>
<Box maxWidth={500}>
<TextField
value={search}
onChange={e => {
setSearch(e.target.value);
}}
fullWidth
InputProps={{
startAdornment: (
<InputAdornment position="start">
<SvgIcon
fontSize="small"
color="action"
>
<SearchIcon />
</SvgIcon>
</InputAdornment>
)
}}
placeholder="Recherchez un évenement"
variant="outlined"
/>
</Box>
{/* <Button
color="primary"
variant="contained"
onClick = {alert(JSON.stringify(dateReel))}
>
Rechercher
</Button> */}
</CardContent>
</Card>
</Box>
<Grid>
<Grid spacing={1} md={8} xs={12} style={{ margin: 2 }}>
{filteredEven.map((recherche, index) => (
<Accordion style={{ marginTop: 30 }} >
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1a-content"
id="panel1a-header"
style={{ backgroundColor: '#DADFD9' }}
>
<Grid container spacing={1} md={12} xs={12} style={{ margin: 0 }}>
<Grid item md={2} xs={4}>
{recherche.date_even.slice(0, 10)}
</Grid>
<Grid item md={2} xs={2}>
{recherche.prix_even}
</Grid>
<Grid item md={2} xs={3}>
{recherche.statut}
</Grid>
<Grid item md={3} xs={3}>
{recherche.descrip_evene}
</Grid>
<Grid item md={3} xs={8} style={{ marginTop: -10 }}>
<IconButton>
<EditProjAdminE
dataSearch={dataSearch}
setDataSearch={setDataSearch}
id={recherche.id}
/>
</IconButton>
<IconButton
onClick={async () => {
suppression(recherche.id)
window.location.reload(false)
}}
>
<DeleteIcon fontSize="small" style={{ color: 'black' }} />
</IconButton>
{/* <SpeedDialTooltipOpen/> */}
</Grid>
</Grid>
</AccordionSummary>
<AccordionDetails>
<List>
<ListItem>
<ListItemText primary={
<Typography variant="caption" style={{ fontWeight: 'bold', fontSize: 16 }}>
{recherche.id}
</Typography>
}
secondary="Membre concerné"
/>
</ListItem>
<ListItem>
<ListItemText primary={
<Typography variant="caption" style={{ fontWeight: 'bold', fontSize: 16 }}>
{recherche.lieu}
</Typography>
}
secondary="Lieu"
/>
</ListItem>
<ListItem>
<ListItemText primary={
<Typography variant="caption" style={{ fontWeight: 'bold', fontSize: 16 }}>
{recherche.heure}
</Typography>
}
secondary="Heure"
/>
</ListItem>
</List>
</AccordionDetails>
</Accordion>
))}
</Grid>
</Grid>
<AjoutEven />
</>
</Card>
);
};
// Results.propTypes = {
// className: PropTypes.string,
// dataEleve: PropTypes.array.isRequired
// };
export default ProjetAdminE;
editProjetEven.js
import React, { useState } from 'react';
import clsx from 'clsx';
import PropTypes from 'prop-types';
import moment from 'moment';
import PerfectScrollbar from 'react-perfect-scrollbar';
import { makeStyles, useTheme, withStyles } from '#material-ui/core/styles';
import {
Button,
Grid,
MenuItem,
DialogContent,
DialogActions,
Dialog,
IconButton,
Avatar,
TextField,
DialogTitle,
} from '#material-ui/core';
import getInitials from 'src/utils/getInitials';
import CreateIcon from '#material-ui/icons/Create';
import EditIcon from '#material-ui/icons/Edit';
import DeleteIcon from '#material-ui/icons/Delete';
const useStyles = makeStyles((theme) => ({
root: {
width: 645,
},
item: {
height: 50
},
buttonDial: {
color: "#fff",
},
buttonAnnuler: {
color: "red"
},
buttonSave: {
background: "#558b2f",
color: "#558b2f",
}
}));
export default function EditProjAdminE(setDataSearch,dataSearch,data,setData,id,index) {
const classes = useStyles();
const [open, setOpen] = React.useState(false);
const [opens, setOpens] = React.useState(false);
const handleChange = event => {
const { name, value } = event.target
setDataSearch({ ...dataSearch, [name]: value })
}
// const fullScreen = useMediaQuery(theme.breakpoints.down(645));
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
// const handleInputChange = event => {
// const { name, value } = event.target
// setData({ ...data, [name]: value })
// }
// const item = dataSearch.find(id);
return (
<div>
<div display="flex">
<IconButton onClick={handleClickOpen}>
<EditIcon fontSize="small" alt="modifier" style={{ color: '#205723' }} />
</IconButton>
</div>
<Dialog
fullWidth
// fullScreen
open={open }
onClose={handleClose}
aria-labelledby="responsive-dialog-title"
maxWidth = 'md'
>
{/* { index ==="" ? "aucune information":
<> */}
<DialogTitle id="responsive-dialog-title">Virement</DialogTitle>
<DialogContent >
<Grid container spacing={1}>
<Grid item md={4} xs={12}>
<TextField
fullWidth
margin="dense"
type="text"
name="prix_even"
value={dataSearch.prix_even}
// defaultValue={dataSearch.prix_even}
label="Prix"
variant="outlined"
onChange={(event) => handleChange(event)}
/>
</Grid>
<Grid item md={4} xs={12}>
<TextField
fullWidth
margin="dense"
type="text"
name="heure"
value={dataSearch.heure}
label="Heure"
variant="outlined"
onChange={(event) => handleChange(event)}
/>
</Grid>
<Grid item md={4} xs={12}>
<TextField
fullWidth
margin="dense"
type="text"
name="lieu"
value={dataSearch.lieu}
label="Lieu"
variant="outlined"
onChange={(event) => handleChange(event)}
/>
</Grid>
<Grid item md={4} xs={12}>
<TextField
fullWidth
margin="dense"
type="date"
name="date_even"
value={dataSearch.date_even}
helperText="Date de l'événement"
variant="outlined"
onChange={(event) => handleChange(event)}
/>
</Grid>
<Grid item md={4} xs={12}>
<TextField
fullWidth
margin="dense"
type="text"
name="descrip_even"
value={dataSearch.descrip_even}
label="Descr de l'événement"
variant="outlined"
onChange={(event) => handleChange(event)}
/>
</Grid>
<Grid item md={4} xs={12}>
<TextField
fullWidth
margin="dense"
type="text"
name="statut"
value={dataSearch.statut}
label="Statut"
variant="outlined"
onChange={(event) => handleChange(event)}
/>
</Grid>
</Grid>
</DialogContent>
<DialogActions>
<Button
// onClick={alert(JSON.stringify(dataSearch))}
>
Modifier
</Button>
<Button onClick={handleClose} className={classes.buttonAnnuler}>
Fermer
</Button>
</DialogActions>
{/* </>
} */}
</Dialog>
</div>
);
}
on click I pass the index of the object to the array and send it to a new array that I created
<IconButton onClick={async () => {
setData({ ...dataSearch[index] })
handleClickOpen()
}}
>
<EditIcon fontSize="small" alt="modifier" style={{ color: '#205723' }} />
</IconButton>
The handleClickOpen seems to be only opening the dialog box and not invoking setDataSearch({ ...dataSearch, [name]: value }) which seems to be responsible to add values to the dataSearch object that is used in your form fields.
I would personally double check if the EditProjAdminE component is receiving the proper dataSearch and then later call a similar function to handleChange when the open event is triggered.
Sorry for the question, maybe it is very silly but I am learning and I have not been able to solve it, I took the signup template from material-ui and decided to perform the validations with react hook forms and everything works but I wanted to add the function of showing or hiding the password with it eye icon, it turns out that when I manage to do it, it is changing the field type from "text-field" to "FormControl" but they no longer show me the help messages when there is an error.
In the code there are 2 password fields, the first works as I want but without the hide / unhide and the second has the icon but as I mentioned it does not show the message.
Something that strikes me is that it turns red correctly when there is an error.
I would appreciate if you could help me make it work properly. Thank you
import React, {useState} from 'react';
import Avatar from '#material-ui/core/Avatar';
import Button from '#material-ui/core/Button';
import CssBaseline from '#material-ui/core/CssBaseline';
import TextField from '#material-ui/core/TextField';
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';
import Visibility from '#material-ui/icons/Visibility';
import VisibilityOff from '#material-ui/icons/VisibilityOff';
import InputAdornment from '#material-ui/core/InputAdornment';
import IconButton from '#material-ui/core/IconButton';
import FormControl from '#material-ui/core/FormControl';
import clsx from 'clsx';
import InputLabel from '#material-ui/core/InputLabel';
import * as yup from 'yup'
import { yupResolver } from '#hookform/resolvers';
import { useForm} from "react-hook-form";
import { OutlinedInput } from '#material-ui/core';
function Copyright() {
return (
<Typography variant="body2" color="textSecondary" align="center">
{'Copyright © '}
<Link color="inherit" href="https://material-ui.com/">
Your Website
</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,
},
margin: {
margin: theme.spacing(1),
},
form: {
width: '100%', // Fix IE 11 issue.
marginTop: theme.spacing(3),
},
submit: {
margin: theme.spacing(3, 0, 2),
},
}));
const RegisterSchema = yup.object().shape({
password: yup
.string()
.trim()
.required('Requerido.')
.min(8, 'Contraseña es muy corta - Debe contener al menos 8 caracteres.')
.max(15, 'Contraseña es muy larga - Debe contener máximo 15 caracteres.')
.matches(/[a-zA-Z]/, 'Contraseña solo puede contener letras latinas.')
});
export default function SignUp() {
const classes = useStyles();
const [data, setData] = useState({
password:'',
showPassword: false,
});
const handleChange = (prop) => (event) => {
setData({ ...data, [prop]: event.target.value });
};
const handleClickShowPassword = () => {
setData({ ...data, showPassword: !data.showPassword });
};
const handleMouseDownPassword = (event) => {
event.preventDefault();
};
const handleInputChange = (e) => {
console.log(e.target.value);
setData ({
...data,
fullName: (data.firstName + ' ' + data.lastName),
[e.target.name] : e.target.value,
})
}
const {register, handleSubmit, errors} = useForm({
resolver: yupResolver(RegisterSchema),
});
const onSubmit = (data) => {
console.log(data);
};
return (
<Container component="main" maxWidth="xs">
<CssBaseline />
<div className={classes.paper}>
<Avatar className={classes.avatar}>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
Registro
</Typography>
<form className={classes.form} noValidate onSubmit={handleSubmit(onSubmit)}>
<Grid container spacing={2}>
{<Grid item xs={12}>
<TextField
variant="outlined"
required
fullWidth
name="password"
label="Contraseña"
type="password"
id="password"
autoComplete="current-password"
onChange={handleInputChange}
inputRef={register}
error ={!!errors.password}
helperText={errors.password ? errors.password.message : ''}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
edge="end"
>
{data.showPassword ? <Visibility /> : <VisibilityOff />}
</IconButton>
</InputAdornment>
}
/>
</Grid>}
<FormControl
className={clsx(classes.margin, classes.textField)}
variant="outlined"
autoComplete="current-password"
inputRef={register}
error ={!!errors.password}
helperText={errors.password ? errors.password.message : ''}
name="password"
type="password"
id="password"
fullWidth
required
>
<InputLabel
htmlFor="outlined-adornment-password">
Contraseña
</InputLabel>
<OutlinedInput
id="outlined-adornment-password"
type={data.showPassword ? 'text' : 'password'}
value={data.password}
onChange={handleChange('password')}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
edge="end"
>
{data.showPassword ? <Visibility /> : <VisibilityOff />}
</IconButton>
</InputAdornment>
}
labelWidth={92}
/>
</FormControl>
</Grid>
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
className={classes.submit}
>
Registrate
</Button>
<Grid container justify="flex-end">
<Grid item>
<Link href="#" variant="body2">
¿Tienes una cuenta? Ingresa
</Link>
</Grid>
</Grid>
</form>
</div>
<Box mt={5}>
<Copyright />
</Box>
</Container>
);
}
In your password Text Field component
you may use this solution , try adding some state to your component that defines whether the user want to show or hide the password and name it for example "showPassword"
const [showPassword,setShow] = useState(false)
<TextField
variant="outlined"
required
fullWidth
name="password"
label="Contraseña"
type={showPassword?"text":"password"}
/>
call setShow(!showPassword) when ever the user click on eye button
Now when ever setShow changes to " true " , the type of the input will be text and thus the password will be shown
Try this. It's worked for me.
<TextField
label='Password'
fullWidth
required
type={showPassword ? 'text' : 'password'}
error={!!errors['password']}
helperText={errors['password'] ? errors['password'].message : ''}
{...register('password')}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
edge="end"
>
{showPassword ? <Visibility /> : <VisibilityOff />}
</IconButton>
</InputAdornment>
)
}}
/>
I have this code and tried to convert it to functional component and I am stuck. I have a form in return() part that passes the value to the state and then to props? via mapStateToProps as far as I understand... But, switching to function() component, I am lost what I have to do here.
class Login extends Component {
state = {
login: '',
password: '',
keepLogged: false
};
changeValue = event => {
event.preventDefault();
const value = event.target.value;
const name = event.target.name;
this.setState({
[name]: value
});
};
loginUser = () => {
const { login, password } = this.state;
const { requestSignIn } = this.props;
requestSignIn({ login, password });
};
render() {
const { login, password } = this.state;
return (
<LoginWrapper>
<Container style={{ border: '1px solid #757575', padding: '5%' }}>
<Row>
<Col style={{ textAlign: 'right', marginRight: '25px' }}>
</Col>
</Row>
<Row>
<Col>
<LoginHeader>Log In to Your Account</LoginHeader>
</Col>
</Row>
<Row>
<Col>
<LoginForm>
<FormControl
name='login'
type='text'
placeholder='Username/Email'
value={login}
onChange={this.changeValue}
style={{ marginBottom: '10px' }}
/>
<FormControl
name='password'
type='password'
placeholder='Password'
value={password}
onChange={this.changeValue}
style={{ marginBottom: '10px' }}
/>
<Button
variant='info'
value='Log In'
onClick={() => this.loginUser()}
>
Log In
</Button>
</LoginForm>
</Col>
</Row>
<Row>
<Col>
<LoginBottom
onClick={() => history.push('/registration')}
style={{ marginTop: '30px' }}
>
Need an account?{' '}
<Link style={{ color: '#007bff' }}>Sign Up</Link>
</LoginBottom>
</Col>
</Row>
</Container>
</LoginWrapper>
)
const mapDispatchToProps = dispatch => ({
requestSignIn: data => dispatch(requestSignIn(data))
});
export default connect(null, mapDispatchToProps)(Login);
So far, I have done this. I am stuck here. Tried to introduce useState for each login, password, and keepLogged but failed :/
function Login(props) {
const [inputs, setInputs] = useState({
// you can login with email or username
login: '',
password: '',
keepLogged: false
});
const { login, password } = inputs;
function handleChange(e) {
e.preventDefault();
const { name, value } = e.target;
setInputs(inputs => ({ ...inputs, [name]: value }));
}
const loginUser = () => {
const setInputs = inputs;
const { requestSignIn } = props;
requestSignIn({ setInputs });
};
return (
<Grid container component='main' className={classes.root}>
<CssBaseline />
<Grid item xs={false} sm={4} md={7} className={classes.image} />
<Grid item xs={12} sm={8} md={5} component={Paper} elevation={6} square>
<div className={classes.paper}>
<div>
<img src={Logo} style={{ width: 300 }} />
</div>
<Typography component='h1' variant='h5'>
Sign in
</Typography>
<form className={classes.form} noValidate>
<TextField
variant='outlined'
margin='normal'
required
fullWidth
id='email'
label='Email Address'
value={login}
onChange={handleChange}
name='login'
autoComplete='email'
autoFocus
/>
<TextField
variant='outlined'
margin='normal'
required
fullWidth
name='password'
label='Password'
value={password}
onChange={handleChange}
type='password'
id='password'
autoComplete='current-password'
/>
<FormControlLabel
control={<Checkbox value='remember' color='primary' />}
label='Remember me'
/>
<Button
type='submit'
fullWidth
variant='contained'
color='primary'
value='Log In'
className={classes.submit}
onClick={() => loginUser()}
>
Sign In 🙂
</Button>
<Grid container>
<Grid item xs>
<Link href='#' variant='body2'>
Forgot password?
</Link>
</Grid>
<Grid item>
<Link
variant='body2'
onClick={() => history.push('/registration')}
>
{"Don't have an account? Sign Up"}
</Link>
</Grid>
</Grid>
<Box mt={5}>
<Copyright />
</Box>
</form>
</div>
</Grid>
</Grid>
)
const mapDispatchToProps = dispatch => ({
requestSignIn: data => dispatch(requestSignIn(data))
});
export default connect(null, mapDispatchToProps)(Login);
I think you were most of the way there, just a case of clearing up some redundant code.
const [inputs, setInputs] = useState({
login: '',
password: '',
keepLogged: false
});
const { login, password } = inputs;
function handleChange(e) {
e.preventDefault();
const { name, value } = e.target;
// Set the inputs object directly, no need to callback
setInputs({ ...inputs, [name]: value });
}
const loginUser = () => {
const { requestSignIn } = props;
// Login and password are already initialised
requestSignIn({login, password});
};
You may also want to pass the event object to the handler like so:
onChange={e => handleChange(e)}