Reputation: 749
I am currently trying to make a login/signup form whose components will render differently depending on if the user toggles "Log In" or "Sign In" (see ColorToggleButton
). I used a React hook whose parameters I pass to the different function components to change their state. On initial rendering, the "Log In" settings show; however, when pressing "Sign In", it seems only LogInOrSignIn
changes rendering to the sign in components. Furthermore, any further toggling doesn't change any rendering after that.
import React, { useState, useEffect } 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 ToggleButton from '@mui/material/ToggleButton';
import ToggleButtonGroup from '@mui/material/ToggleButtonGroup';
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>
);
}
function ColorToggleButton(props) {
const handleChange = (event) => {
props.toggle(event.value)
};
return (
<>
<ToggleButtonGroup
color="primary"
value={props.status}
exclusive
onChange={handleChange}
>
<ToggleButton value="login">Log In</ToggleButton>
<ToggleButton value="signin">Sign In</ToggleButton>
</ToggleButtonGroup>
</>
);
}
function SubmitButton(props) {
let buttonText;
if (props.status === "signin") {
buttonText = "Sign Up"
} else {
buttonText = "Log In"
}
return (
<Button
type="submit"
fullWidth
variant="contained"
sx={{ mt: 3, mb: 2 }}
>
{buttonText}
</Button>
)
}
function LogInOrSignIn(props) {
if (props.status === "login") {
return (
<>
<TextField
margin="normal"
required
fullWidth
id="email"
label="Email/Username"
name="email"
autoComplete="email"
autoFocus
/>
<TextField
margin="normal"
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
autoComplete="current-password"
/>
</>
)
}
return (
<>
<TextField
margin="normal"
required
fullWidth
id="username"
label="Username"
name="username"
autoComplete="email"
autoFocus
/>
<TextField
margin="normal"
required
fullWidth
id="email"
label="Email"
name="email"
autoComplete="email"
autoFocus
/>
<TextField
margin="normal"
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
autoComplete="current-password"
/>
</>
)
}
function ForgotPassword(props) {
if (props.status === "signin") {
return null;
}
return (
<>
<Grid container>
<Grid item xs>
<Link href="#" variant="body2">
Forgot password?
</Link>
</Grid>
</Grid>
</>
)
}
const theme = createTheme();
function LogIn() {
const [userStatusContext, setState] = useState("login");
const handleSubmit = (event) => {
event.preventDefault();
const data = new FormData(event.currentTarget);
// eslint-disable-next-line no-console
console.log({
email: data.get('email'),
password: data.get('password'),
});
};
return (
<ThemeProvider theme={theme}>
<Container component="main" maxWidth="xs">
<CssBaseline />
<Box
sx={{
marginTop: 8,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
}}
>
<Avatar sx={{ m: 1, bgcolor: 'secondary.main' }}>
<LockOutlinedIcon />
</Avatar>
<ColorToggleButton toggle={setState} status={userStatusContext}/>
<Typography component="h1" variant="h5">
Sign in
</Typography>
<Box component="form" onSubmit={handleSubmit} noValidate sx={{ mt: 1 }}>
<LogInOrSignIn status={userStatusContext}/>
<SubmitButton status={userStatusContext}/>
</Box>
<ForgotPassword status={userStatusContext}/>
</Box>
<Copyright sx={{ mt: 8, mb: 4 }} />
</Container>
</ThemeProvider>
);
}
export default LogIn;
I'm not really sure what's going on. I had thought React would re-render all affected function components that depend on the state hook that I use, if it changes. Any advice would be much appreciated.
Upvotes: 0
Views: 240
Reputation: 198
the problem is in function ColorToggleButton(props)
. you did not pass the toggle value to parent component. also you do not need to pass the value as a prop to ColorToggleButton
.
function ColorToggleButton(props) {
const [value, setValue] = useState("login")
const handleChange = (event) => {
setValue(event.value);
props.toggle(event.value);
};
return (
<>
<ToggleButtonGroup
...
value={value}
...
function Login(){
<ColorToggleButton toggle={(value)=>setState(value)} />
}
this is the rough idea and did not check my code. you can give it a go.
Upvotes: 1