I'm trying to get the hang of react/redux with a login page to expand my knowledge. I am having some issues with the following error:
Invalid hook call. Hooks can only be called inside of the body of a function component.
I know this has been posted on here a lot but none of the answers are sticking for me. i can get the store to work just fine in other parts of of app just having some trouble with the logic here. any help is appreciated. My login page is this:
import React, { useState } from "react";
import { Grid, CircularProgress, Typography, Button, Tabs, Tab, TextField, Fade } from "@material-ui/core";
import { withRouter } from "react-router-dom";
import useStyles from "./styles";
import logo from "./logo.svg";
import { LoginUser } from "../../comps/Userauth";
function Login(props) {
var classes = useStyles();
var [isLoading, setIsLoading] = useState(false);
var [error, setError] = useState(null);
var [activeTabId, setActiveTabId] = useState(0);
var [loginValue, setLoginValue] = useState("");
var [passwordValue, setPasswordValue] = useState("");
return (
<Grid container className={classes.container}>
<div className={classes.logotypeContainer} style={{zIndex: '1'}} >
<img src={logo} alt="logo" className={classes.logotypeImage} />
<Typography className={classes.logotypeText}>test app</Typography>
</div>
<div className={classes.formContainer}>
<div className={classes.form}>
<Tabs
value={activeTabId}
onChange={(e, id) => setActiveTabId(id)}
indicatorColor="primary"
textColor="primary"
centered
>
<Tab label="Login" classes={{ root: classes.tab }} />
</Tabs>
{activeTabId === 0 && (
<React.Fragment>
<Fade in={error}>
<Typography color="secondary" className={classes.errorMessage}>
Please try again.
</Typography>
</Fade>
<TextField
id="username"
InputProps={{
classes: {
underline: classes.textFieldUnderline,
input: classes.textField,
},
}}
value={loginValue}
onChange={e => setLoginValue(e.target.value)}
margin="normal"
placeholder="Username"
type="text"
fullWidth
/>
<TextField
id="password"
InputProps={{
classes: {
underline: classes.textFieldUnderline,
input: classes.textField,
},
}}
value={passwordValue}
onChange={e => setPasswordValue(e.target.value)}
margin="normal"
placeholder="Password"
type="password"
fullWidth
/>
<div className={classes.formButtons}>
{isLoading ? (
<CircularProgress size={26} className={classes.loginLoader} />
) : (
<Button
disabled={
loginValue.length === 0 || passwordValue.length === 0
}
onClick={() =>
LoginUser(
loginValue,
passwordValue,
props.history,
setIsLoading,
setError,
)
}
variant="contained"
color="primary"
size="large"
>
Login
</Button>
)}
</div>
</React.Fragment>
)}
</div>
</div>
</Grid>
);
}
export default withRouter(Login);
And the userauth req:
import React from "react";
import axios from "axios";
import {useSelector, useDispatch} from 'react-redux'
import allActions from '../actions'
var jwtDecode = require('jwt-decode');
function LoginUser(login, password, history, setIsLoading, setError) {
const currentUser = useSelector(state => state.currentUser)
const dispatch = useDispatch()
try {
setError(false);
setIsLoading(true);
axios.post('/login', {username: login, password: password}, {
}).catch(function (error) {
if (error.response) {
setError(true);
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
setError(true);
console.log(error.request);
} else {
setError(true);
console.log('Error', error.message);
}
}).then(function(response) {
if (response.status == '200') {
setTimeout(() => {
setError(null)
setIsLoading(false)
let token1 = jwtDecode(response.data.token);
dispatch(allActions.userActions.setUser(token1.username))
history.push('/app/dashboard')
}, 2000);
} else {
setError(true);
setIsLoading(false);
}
})
} catch (error) {
setError(true);
setIsLoading(false);
}
}
function signOut(dispatch, history) {
dispatch(allActions.userActions.logOut())
history.push("/login");
}
export { LoginUser, signOut };