How to invoke a hook from React class component? - reactjs

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),
},
}));

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.

Related

Link to another component using material UI link using React JS

I'm completely new to React and been trying a few hours now to link to another component that I've made. I have this log-in form that I want to link to my sign up page once a material ui link is clicked. I've been searching a ton, but I can't just get it to work.
This is my login-component:
import React from 'react';
import {useState} 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 { BrowserRouter, Route, Routes} from 'react-router-dom';
import Grid from '#mui/material/Grid';
import Box from '#mui/material/Box';
import Typography from '#mui/material/Typography';
import Container from '#mui/material/Container';
import { createTheme, ThemeProvider } from '#mui/material/styles';
import Link from '#mui/material/Link';
import RegisterPage from './Register';
import { Link as RouterLink } from "react-router-dom";
const Register = () => (
<BrowserRouter>
<Routes>
<Route exact path="/register" element={<RegisterPage />} />
</Routes>
</BrowserRouter>
);
function LoginCard({ Login, error }) {
const [details, setDetails] = useState({ username: "", password: "" })
const onFormSubmit = (e) => {
e.preventDefault();
Login(details);
}
const theme = createTheme();
function Copyright(props) {
return (
<Typography variant="body2" color="text.secondary" align="center" {...props}>
{'Copyright © '}
<Link color="inherit" href="https://mui.com/">
Fiin Frisører
</Link>{' '}
{new Date().getFullYear()}
{'.'}
</Typography>
);
}
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' }}>
</Avatar>
<Typography component="h1" variant="h5">
Sign in
</Typography>
<Box component="form" onSubmit={onFormSubmit} noValidate sx={{ mt: 1 }}>
<TextField
margin="normal"
required
fullWidth
id="username"
label="Username"
name="username"
onChange={e=> setDetails({...details, username: e.target.value})}
/>
<TextField
margin="normal"
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
onChange={e=> setDetails({...details, password: e.target.value})}
/>
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Remember me"
/>
<Button
type="submit"
fullWidth
variant="contained"
sx={{ mt: 3, mb: 2 }}
>
Sign In
</Button>
<Grid container>
<Grid item xs>
<Link href="#" variant="body2">
Forgot password?
</Link>
</Grid>
<Grid item>
**<Link href="https://www.google.com" variant="body2">
Don't have an account yet?
</Link>**
</Grid>
</Grid>
</Box>
</Box>
<Copyright sx={{ mt: 8, mb: 4 }} />
</Container>
</ThemeProvider>
);
};
export default LoginCard;
Once I click the Link that wraps the text "Dont have an account yet?" I want to redirect to another component showing only my Register component.
Been trying to add component props to the link, creating a new function and calling that, using href and to-tag but nothing seems to work. Can anyone help me out?
If you want to link to a page internal to your app then you will need to render the Link component from react-router-dom, i.e. the RouterLink in your code. You can specify this to be the rendered component for the MUI Link component. From here you pass any of the normal RRD Link props, like the to prop for the route you are linking to.
Example:
<Link component={RouterLink} to="register" variant="body2">
Don't have an account yet?
</Link>

React Form validation with Material UI TextField And Typscript is not working

I try to write a code of "sign up" page with MUI library using react with typescript.
in each TextFeild tag I added "required"
but on submit, the validation is not working.
I looked for any other validation but I didn't find other way on MUI website.
can you help me? thanks advance.
this is the sign up component code:
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 globals from '../../Utils/Globals';
import { useForm } from 'react-hook-form';
import axios from 'axios';
import notify from '../../Utils/Notify';
import { SysErrs } from '../../Utils/SysErrs';
import { UserModel } from '../../Models/UserModel';
function Copyright (props: any): JSX.Element {
return (
<Typography variant="body2" color="text.secondary" align="center" {...props}>
{'Copyright © '}
<Link color="inherit" href="https://mui.com/">
Chana Kurtz
</Link>{' '}
{new Date().getFullYear()}
{'.'}
</Typography>
);
}
const URLregister = globals.urls.guest + "register/"
const theme = createTheme();
export default function SignUp() {
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
const data = new FormData(event.currentTarget);
const json = JSON.stringify(Object.fromEntries(data));
console.log(json);
axios.post(URLregister, data)
.then(response => {
notify.success(SysErrs.REGISTERD)
// reset({})
})
.catch(error => {
notify.error(SysErrs.EMAIL_IN_USE)
})
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>
<Typography component="h1" variant="h5">
Sign up
</Typography>
<Box component="form" noValidate onSubmit={handleSubmit} sx={{ mt: 3 }}>
<Grid container spacing={2}>
<Grid item xs={12} sm={6}>
<TextField
autoComplete="given-name"
name="firstName"
required={true}
fullWidth
id="firstName"
label="First Name"
autoFocus
/>
</Grid>
<Grid item xs={12} sm={6}>
<TextField
required={true}
fullWidth
id="lastName"
label="Last Name"
name="lastName"
autoComplete="family-name"
helperText="Min length must be 2 characters"
/>
</Grid>
<Grid item xs={12}>
<TextField
required={true}
fullWidth
id="userName"
label="User Name"
name="userName"
autoComplete="User-Name"
/>
</Grid>
<Grid item xs={12}>
<TextField
required={true}
fullWidth
id="email"
label="Email Address"
name="email"
autoComplete="email"
/>
</Grid>
<Grid item xs={12}>
<TextField
required={true}
fullWidth
name="password"
label="Password"
type="password"
id="password"
autoComplete="new-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>
<Link href="#" variant="body2">
Already have an account? Sign in
</Link>
</Grid>
</Grid>
</Box>
</Box>
<Copyright sx={{ mt: 5 }} />
</Container>
</ThemeProvider>
);
}
You need to wrap this with a FormControl component.
Further documentation here: form control

Matreial ui is not loading Styles and Theme?

I am trying to use this ready free templet for a login page the problem is the source code is different and I had to adapt it to work there is this issue with this import in the src code
#mui/material/
the I had to convert to
#material-ui/
for it to work..
but the problem is my page looks like the following no colors and the theme didn't load for some reason the sx is not working any idea what is the issue here and why the src code is different yet working ?
A. source code
B. material-ui free template view
Source Singup page
My Signup page rendered on next.js localhost
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 { createTheme, ThemeProvider } from '#material-ui/core/styles';
function Copyright(props) {
return (
<Typography variant='body2' color='text.secondary' align='center' {...props}>
{'Copyright © '}
<Link color='inherit' href='https://material-ui.com/'>
Your Website
</Link>{' '}
{new Date().getFullYear()}
{'.'}
</Typography>
);
}
const theme = createTheme();
function SignIn() {
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>
<Typography component='h1' variant='h5'>
Sign 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' />
<Button type='submit' fullWidth variant='contained' sx={{ mt: 3, mb: 2 }}>
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>
</Box>
</Box>
<Copyright sx={{ mt: 8, mb: 4 }} />
</Container>
</ThemeProvider>
);
}
export default SignIn;
Try to use yours TextField with InputProps with color: "inherit"
<TextField
margin='normal'
required
fullWidth
id='email'
label='Email
Address'
name='email'
autoComplete='email'
autoFocus
InputProps={{
style: {
color: "inherit"
}
}}
/>

Module not found: Can't resolve '#material-ui/core/Avatar' in 'D:\own_files\ReactTutorial\react-app\src'

Hi I just started my first application with React. I'm using a simple login component, and after I use npm start it throws this error: Module not found: Can't resolve '#material-ui/core/Avatar' in 'D:\own_files\ReactTutorial\react-app\src'
I have basic React code
Here's my App.js:
import React, { Component } from 'react';
import { BrowserRouter as Router, Route } from "react-router-dom";
import GoodBye from './GoodBye';
import Hello from './Hello';
import NavigationBar from './NavigationBar';
import LoginComponent from './LoginComponent';
class App extends Component {
render() {
return (
<Router>
<div>
<NavigationBar />
<Route path="/hello" component={Hello} />
<Route path="/goodbye" component={GoodBye} />
<Route path="/login" component={LoginComponent} />
</div>
</Router>
);
}
}
export default App;
And my LoginComponent:
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 { makeStyles } from '#material-ui/core/styles';
import Container from '#material-ui/core/Container';
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,
},
form: {
width: '100%', // Fix IE 11 issue.
marginTop: theme.spacing(1),
},
submit: {
margin: theme.spacing(3, 0, 2),
},
}));
export default function SignIn() {
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} noValidate>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="email"
label="Email Address"
name="email"
autoComplete="email"
autoFocus
/>
<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}>
<Copyright />
</Box>
</Container>
);
}
Did you install Material-UI?
npm install #material-ui/core
or use a CDN?
https://material-ui.com/
Module not found: Can't resolve '#mui/icons-material/Add' in 'E:\reacttut\awesomeapp\src'
I was facing same issue. Then I used:
import AddIcon from '#material-ui/icons/Add';
instead of
import AddIcon from '#mui/icons-material/Add';
Add the Following Lines to your package.json "dependencies"
"#material-ui/core": "4.10.0",
"#material-ui/icons": "4.9.1",
"#material-ui/lab": "^4.0.0-alpha.56",
"#material-ui/pickers": "^3.2.10",
and execute command yarn install or npm install

React make components show in column

I am pretty new to React, and I am making my first app using material-ui, and I have managed to render the components I intend, but I haven't been able to print them stacked, they show in line:
I have tried to wrap them with div and p, and I get the same result.
This is the code of my component:
import React, { Component } from 'react';
import Button from '#material-ui/core/Button';
import classNames from 'classnames';
import PropTypes from 'prop-types';
import { withStyles } from '#material-ui/core/styles';
import Input from '#material-ui/core/Input';
import InputLabel from '#material-ui/core/InputLabel';
import InputAdornment from '#material-ui/core/InputAdornment';
import FormControl from '#material-ui/core/FormControl';
import Visibility from '#material-ui/icons/Visibility';
import VisibilityOff from '#material-ui/icons/VisibilityOff';
import IconButton from '#material-ui/core/IconButton';
const styles = theme => ({
root: {
display: 'flex',
flexWrap: 'wrap',
},
margin: {
margin: theme.spacing.unit,
},
withoutLabel: {
marginTop: theme.spacing.unit * 3,
},
textField: {
flexBasis: 200,
},
button: {
margin: theme.spacing.unit,
},
input: {
display: 'none',
},
});
class LoginModal extends Component {
state = {
password: '',
showPassword: false,
};
render() {
const { classes } = this.props
return (
<div className={classes.root}>
<h1>Welcome to My App...</h1>
<FormControl className={classNames(classes.margin, classes.textField)}>
<InputLabel htmlFor="adornment-email">eMail</InputLabel>
<Input i
d="adornment-email"
variant="filled"
/>
</FormControl>
<FormControl className={classNames(classes.margin, classes.textField)}>
<InputLabel htmlFor="adornment-password">Password</InputLabel>
<Input
id="adornment-password"
variant="filled"
type={this.state.showPassword ? 'text' : 'password'}
value={this.state.password}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="Toggle password visibility"
onClick={this.handleClickShowPassword}
>
{this.state.showPassword ? <Visibility /> : <VisibilityOff />}
</IconButton>
</InputAdornment>
}
/>
<p>Did you forget your password?</p>
<Button color="primary" variant="contained">Login</Button>
</FormControl>
</div>
);
};
}
LoginModal.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(LoginModal);
Only the two latest components show stacked, but the rest show in line.
How can I instruct React to display components in an stacked fashion?
update your root style to:
root: {
display: 'flex',
flex-direction: column;
},
you may need to adjust other flex properties to get the alignment you want.
I found that Material-UI uses Grid components to manage responsiveness, and you can use it to arrange objects in display.
This is how I used Grid to display my objects the way I wanted:
class LoginModal extends Component {
state = {
password: '',
showPassword: false,
};
render() {
const { classes } = this.props
return (
<div className={classes.root}>
<Grid container spacing={24}>
<Grid item xs={12}>
<h1>Welcome to My App...</h1>
</Grid>
<Grid item xs={12}>
<FormControl className={classNames(classes.margin, classes.textField)}>
<InputLabel htmlFor="adornment-email">eMail</InputLabel>
<Input
id="adornment-email"
variant="filled"
/>
</FormControl>
</Grid>
<Grid item xs={12}>
<FormControl className={classNames(classes.margin, classes.textField)}>
<InputLabel htmlFor="adornment-password">Password</InputLabel>
<Input
id="adornment-password"
variant="filled"
type={this.state.showPassword ? 'text' : 'password'}
value={this.state.password}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="Toggle password visibility"
onClick={this.handleClickShowPassword}
>
{this.state.showPassword ? <Visibility /> : <VisibilityOff />}
</IconButton>
</InputAdornment>
}
/>
<p>Did you forget your password?</p>
<Button color="primary" variant="contained">Login</Button>
</FormControl>
</Grid>
</Grid>
</div>
);
};
}
And this is the result:

Resources