I have built a login page where on filling the username and password and hitting the submit button, it dispatches the action which basically goes to the backend and checks whether the username and password is valid. I am using React
and redux
and this is my login page below
login.js (simplified)
import LoginHandle from '../login/LoginHandle'
function userLogin(event) {
event.preventDefault()
const username = document.getElementById("username").value
const password = document.getElementById("password").value
LoginHandle(username, password)
}
const Login = () => {
return (
<div className="flex-row align-items-center">
<form onSubmit={(e) => userLogin(e)}>
<h1>Login</h1>
<input id="username" type="email" placeholder="Username" required/>
<input id="password" type="password" placeholder="Password" required/>
<button type="submit" className="px-4">Login</button>
</form>
</div>
)
}
export default Login
LoginHandle.js (simplified)
import {useDispatch, useSelector} from 'react-redux'
import {getLoginStatus} from '../actions/loginAction'
const LoginHandle = (username, password) => {
const dispatch = useDispatch()
dispatch(getLoginStatus(username, password))
const loginState = useSelector(state=> state.loginStatus)
if(loginState.loading) {
console.log("please wait")
}
// .... rest of the logic
}
export default LoginHandle
As you can see I try to dispatch the action and then check the state to get confirmation from the backend. But I get this error
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:...
What am I doing wrong?
import {useDispatch, useSelector} from 'react-redux'
import {getLoginStatus} from '../actions/loginAction'
const useLoginHandler = (username, password, submitted) => {
const dispatch = useDispatch();
const loginState = useSelector(state=> state.loginStatus)
// it is better to put the dispatch inside a useEffect rather than outside
useEffect(() => {
if(!submitted) {return};
dispatch(getLoginStatus(username, password))
}, [username, password, submitted]);
if(loginState.loading) {
console.log("please wait")
}
// .... rest of the logic
}
export default useLoginHandler
And your usage of the hook is wrong. it should not be inside a callback function. it should be at the top level. Something like below. Also you should not access dom elements directly, instead use useRef or useState to get value
const Login = () => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('')
const [submitted, setSubmitted] = useState(false);
useLoginHandler(username, password, submitted); //custom hook should be used at this level
return (
<form onSubmit={(e) => setSubmitted(true)}>
<input id="username" type="email" placeholder="Username" required onChange={e => setUsername(e.target.value)}/>
</form>
)
}