0

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.

1
  • It looks like handleChange should have a second arg: const handleChange = (event, value) => { props.toggle(value) };. Not sure Commented Jan 1, 2022 at 22:28

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.