Very new react user here. I have been troubleshooting this error for hours now. I previously had this component working as a class, but it seems everyone is migrating towards functional components lately, so I'm trying to convert it. I did an intermediate conversion without using state and it worked fine, but I am having trouble converting username and password to state values.
When I use the following code, I get an error:
Uncaught 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.
I have read through the linked troubleshooting page multiple times, and tried fixing all three possible causes with no success.
- I am using
react
17.0.1 andreact-dom
17.0.1 in mydevDependencies
. - I have installed the
eslint-plugin-react-hooks
rule to identify if I am not using hooks correctly in my functional component. - I have used
npm ls react
andnpm ls react-dom
to confirm I do not have duplicate react versions.
LoginForm.jsx
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
const $ = require('jquery');
const LoginForm = ({ onToken }) => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const submit = (event) => {
// DO NOT POST PARAMS
event.preventDefault();
// AJAX username and password
const loginData = {
username: username,
password: password
};
const options = {
url: 'api/login',
type: 'POST',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
data: JSON.stringify(loginData),
success: (data) => {
console.log(data);
onToken(data.token);
}
};
$.ajax(options);
console.log('Submitted!');
};
return (
<form onSubmit={submit}>
<label htmlFor="username">Username:</label><br/>
<input value={username} onChange={e => setUsername(e.target.value)} type="text" id="username" name="username"/><br/>
<label htmlFor="password">Password:</label><br/>
<input value={password} onChange={e => setPassword(e.target.value)} type="password" id="password" name="password"/><br/>
<input type="submit" value="Login"/>
</form>
);
};
LoginForm.propTypes = {
onToken: PropTypes.func
};
export default LoginForm;
I have created a branch on my project's repository so you can view any other information:
Branch: https://github.com/GibsDev/node-password-manager/tree/login-conversion
Commit: https://github.com/GibsDev/node-password-manager/commit/e0714b16bdbbf339fabf1aa4f6eefacd6d053427