0

Question from React newbie! I have Material UI React login form and am trying to use hook within login form. But getting invalid hook call error. No luck so far. Help please.. loginformstyles.js is the hook I am trying to use in the signin.js file.. The login page has two text fields - username and password and a Submit button.

import React 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 FormControlLabel from '@material-ui/core/FormControlLabel';
import Checkbox from '@material-ui/core/Checkbox';
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 Container from '@material-ui/core/Container';
import { ValidatorForm, TextValidator} from 'react-material-ui-form-validator';
import { useStyles } from './loginformstyles';

export default class MyForm extends React.Component {

Copyright() {
  return (
    <Typography variant="body2" color="textSecondary" align="center">
      {'Copyright © '}
      <Link color="inherit" href="https://material-ui.com/">
        Task Manager
      </Link>{' '}
      {new Date().getFullYear()}
      {'.'}
    </Typography>
  );
}

handleChange (event) {
  const email = event.target.value;
  this.setState({ email });
}


render() {
  const classes = useStyles();
  
  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} >
          <TextField
            variant="outlined"
            margin="normal"
            required
            fullWidth
            id="email"
            label="Email Address"
            name="email"
            autoComplete="email"
            autoFocus
            validators={['required', 'isEmail']}
            errorMessages={['this field is required', 'email is not valid']}
            onChange={this.handleChange}
          />
          <TextField
            variant="outlined"
            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"
          />
          <Button
            type="submit"
            fullWidth
            variant="contained"
            color="primary"
            className={classes.submit}
          >
            Sign In
          </Button>
          <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>
      </div>
      <Box mt={8}>
        <this.Copyright />
      </Box>
    </Container>
  );
}
}
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';

export 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%', // Fix IE 11 issue.
      marginTop: theme.spacing(1),
    },
    submit: {
      margin: theme.spacing(3, 0, 2),
    },
  }));
1
  • 2
    You can't use Hooks inside class components. You'll either need to refactor your class to be functional or wrap your component with an HOC. This link might be helpful in the latter: infinum.com/the-capsized-eight/… Commented Jun 27, 2020 at 1:11

1 Answer 1

2

If you just want to make this work, you could wrap the it and then expose the styles into child component, ex.

  const Wrapper = ({ children }) => {
    const classes = useStyles()
    return children(classes)
  }

and then you can do

  <Wrapper> 
    {classes => <Copyright classes={classes} />}
  </Wrapper>

Of course, this is just to get it working. In general you shouldn't mix class and hook, but as long as you can turn them into components, then you can mix and match.

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

3 Comments

Thanks. yes, I know but I just want to get this working... just want to know where to specify the code <Wrapper> For example, In the signin.js render method, <div className={classes.paper}> ... which is a hook prop... how do I change it using <Wrapper> tag
If Copyright is your component, you need to add a prop classes to it so that <Wrapper /> replaces your <Copyright />. The reason is that Wrapper wrap your style inside.
@windmaomao it looks like his component is MyForm, Copyright is just a method that was capitalized.

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.