I don't know why the below code works properly without any error and response is also recorded once the loginHandler()
is fired but once I add the dispatch
function inside the try block after the response has got, the catch block with the check whether a response has been got or not executes!
function Login() {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [msg, setMsg] = useState("");
const dispatch = useDispatch();
const LoginHandler = async (e) => {
e.preventDefault();
try {
const response = await axios.post(
LOGIN_URL,
JSON.stringify({ username, password }),
{
headers: { "Content-Type": "application/json" },
withCredentials: false,
}
);
console.log(JSON.stringify(response?.data?.access));
dispatch(
login({
username: username,
accessToken: response?.data?.access,
})
);
const userName = useSelector((state) => state.user.value.userName);
const accessToken = useSelector(
(state) => state.user.value.userAccessToken
);
console.log("USER NAME STORED IN STORE = " + userName);
console.log("USER ACESS TOKEN STORED IN STORE = " + accessToken);
setMsg("Login Successful!");
} catch (err) {
if (!err?.response) {
console.log("NO SERVER RESPONSE");
setMsg("NO SERVER RESPONSE!");
} else {
console.log("SOMETHING WRONG!");
setMsg("SOMETHING WENT WRONG!");
}
}
};
return (
<LoginForm />
);
}
export default Login;
The Error I get is,
react-dom.development.js:16227 Uncaught (in promise) 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:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
at Object.throwInvalidHookError (react-dom.development.js:16227:9)
at useContext (react.development.js:1618:21)
at useReduxContext (useReduxContext.js:21:24)
at useSelector2 (useSelector.js:40:9)
at LoginHandler (Login.jsx:49:22)
I have also tried to put the dispatch
function inside another function and then call it, but the problem persists!
The issue it seems is that the code is attempting to use the useSelector
hook in a nested function, which breaks the Rules of Hooks.
Only Call Hooks at the Top Level
Don’t call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function, before any early returns. By following this rule, you ensure that Hooks are called in the same order each time a component renders. That’s what allows React to correctly preserve the state of Hooks between multiple
useState
anduseEffect
calls.
Move the useSelector
calls out of the callback, or just reference the response values directly.
Use the useEffect
hook if you care to log the updated state values.
Example:
function Login() {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [msg, setMsg] = useState("");
const dispatch = useDispatch();
const userName = useSelector((state) => state.user.value.userName);
const accessToken = useSelector(
(state) => state.user.value.userAccessToken
);
useEffect(() => {
console.log("USER NAME STORED IN STORE = " + userName);
console.log("USER ACCESS TOKEN STORED IN STORE = " + accessToken);
}, [userName, accessToken]);
const LoginHandler = async (e) => {
e.preventDefault();
try {
const response = await axios.post(
LOGIN_URL,
JSON.stringify({ username, password }),
{
headers: { "Content-Type": "application/json" },
withCredentials: false,
}
);
console.log(JSON.stringify(response?.data?.access));
dispatch(
login({
username: username,
accessToken: response?.data?.access,
})
);
console.log("USER NAME USED = " + username);
console.log("USER ACCESS TOKEN RETURNED = " + response?.data?.access);
setMsg("Login Successful!");
} catch (err) {
if (!err?.response) {
console.log("NO SERVER RESPONSE");
setMsg("NO SERVER RESPONSE!");
} else {
console.log("SOMETHING WRONG!");
setMsg("SOMETHING WENT WRONG!");
}
}
};
return (
<LoginForm />
);
}
export default Login;